JS Hash Function Reversal? - javascript

I have this function that I found to hash a string, I have been attempting for some hours now to reverse this function to take the hash and return the string. I am not too familiar with left and right shifts, what exactly do they do in the case of this function and would reversing it be even possible? I have used the string "luxor" for my tests and I get "250B0C5E" as the hash but have been unable to get a string back that matches "luxor". I have attempted switching the shifts from left to right and moving the charcodeat but still no success.
function HashString(command) {
let hash = 0;
let string = command.toLowerCase();
for(let i=0; i < string.length; i++) {
let letter = string[i].charCodeAt();
hash = hash + letter;
hash += (hash << 10 >>> 0);
hash ^= (hash >>> 6);
hash = hash >>> 0
}
hash += (hash << 3);
if (hash < 0) {
hash = hash >>> 0
}
hash ^= (hash >>> 11);
hash += (hash << 15);
if (hash < 0) {
hash = hash >>> 0
}
return hash.toString(16).toUpperCase();
}

You can't.
Hashing is a one-way process. When it's a two-way process, it's encryption/decryption. They have very different uses.
This is just a hash function. It takes a string (a series of 16-bit values) and produces a single number (an IEEE-754 double-precision floating point value, a "double") which it then turns into a hex string. But in places during that process, the value is reduced to 32 bits because of the bit shift operators, which convert the double to a 32-bit two's complement integer before doing their work, then convert it back to an equivalent double.
You can't reverse that process, it's lossy (it loses information). There isn't room in a 32-bit value to store the information needed to replicate a string of 16-bit values of any length; it could handle two chars without being lossy, or four if you limit the range to chars where the upper byte of the 16-bit value is 0, but that's it.

Related

Javascript: converting very large and very small numbers to a fixed human readbale string

I have the following function which I thought would convert very large e.g., 1e+24 and very small, e.g., 1e-18 numbers to a fixed string, e.g., 1000000000000000000000000:
convertExponentialToDecimal (exponentialNumber) {
// Sanity Check - i.e., is it exponential number?
const str = exponentialNumber.toString()
if (str.indexOf('e-') !== -1) {
const exponent = parseInt(str.split('-')[1], 10)
return exponentialNumber.toFixed(exponent)
}
if (str.indexOf('e+') !== -1) {
const exponent = parseInt(str.split('+')[1], 10)
return exponentialNumber.toFixed(exponent)
}
return exponentialNumber
}
However, for very large numbers - the process seems not to be working ...
i.e., a conversion of 1e+24 yields 1e+24, but 1e-18 yields 0.000000000000000001 as expected.
Can anyone spot the obvious issues, or have any pointers or even their own working solution for such a scenario...
If this is any insight - it works for anything less than 1e+21 ...
For your 'very large' part:
if (str.indexOf('e+') !== -1) {
let [a,b] = str.split('+')
a = a.slice(0,-1)
if (a.indexOf('.') !== -1) {
b = parseInt(b) - (a.length - a.indexOf('.') -1)
}
return a.replace('.','')+"".padEnd(b,0)
}
For your 'very small' part (though this would need to be tested, it works on my example but i didn't go through corner cases) :
if (str.indexOf('e-') !== -1) {
const [a,b] = str.split('-')
return '0.'+a.slice(0,-1).padStart(b,0).replace('.','')
}
Number type is IEEE754 float with double precision behind the curtain and it doesn't have enough precision to represent 1e24 digits. If you want to avoid treating numbers as strings, consider BigInt data type.
There are BigInt literals with n suffix and they don't support exponential notation, but luckily they do support **. For big numbers, you can use
10n**24n; // 1000000000000000000000000n
BigInts, are Int, without decimal point. But they are also Big, so you can afford fixed point notation, like first thousand digits are integer part, second thousand digits decimal part (the maximum size depends on available memory).

Efficiently iterate over binary numbers and check the value of a bit in Javascript?

I need to iterate over the numbers from 0 to X and for each number, i, I need to check whether the bits at positions a, b, c, d, e are true or false.
Is there an easy way to do this that is efficient in Javascript? Currently I am thinking of manually iterating over the numbers, converting them to binary strings, and then doing string[a] === "0" or something.
There is a way to do this, you can use bitwise operators
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
Basically, you have your &, | and XOR operators, that you can use and combine to get the results you want.
If for example you want to check if the number 2 (10 in binary), has a a bit turned on in the 2nd index, you can use the expression
2 & 2 > 0. The expression will return true.
You want to & the number you want to check, with the number that has a bit turned on only in the index you want to check, if you want to check if index 3 has a bit turned on, use the number 4 (100 in binary) to compare against.
I ended up doing:
for (let i = 0; i < Math.pow(2, k); ++i) {
for (let j = 0; j < k; ++j) {
const jthBitIsSet = (i & (1 << j)) !== 0;
// rest of code...
}
}
k effects the number of leading 0s. For example, if k = 3, then 1 becomes 001.

Decode a byte array to a signed integer up to 64 bit

I know that JavaScript can't precisely represent all 64 bit integer numbers. But it can precisely represent numbers larger than 32 bit. And that's what I need. With whatever precision JavaScript can give me.
I have a byte array of known length. It has 1, 2, 4, 8 or 16 bytes. And it can contain a signed or unsigned integer, I know which it is. The data is big-endian (network byte order).
How can I get the number value from that byte array?
There are simple solitions that completely fail on negative numbers. There's DataView that isn't of any help with more than 32 bits. I'm interested in a nice and simple and preferable efficient pure JavaScript solution to handle this. There doesn't seem to be any solution for this in the part of the web that's visible to me.
In case somebody wants to see wrong code, here is my version of positive numbers:
function readInt(array) {
var value = 0;
for (var i = array.length - 1; i >= 0; i--) {
value = (value * 256) + array[i];
}
return value;
}
This page explains a good and simple solution:
Add up all bits from the right end, up to the second most significant bit.
The most significant bit is not added as 2^i but as -2^i.
My code works in a larger scope that has an array and a pos to read from.
function readInt(size) {
var value = 0;
var first = true;
while (size--) {
if (first) {
let byte = array[pos++];
value += byte & 0x7f;
if (byte & 0x80) {
value -= 0x80; // Treat most-significant bit as -2^i instead of 2^i
}
first = false;
}
else {
value *= 256;
value += array[pos++];
}
}
return value;
}
The raw bytes are provided in array (a Uint8Array) and pos is the next index to read. This function starts to read at the current pos and advances pos as it reads one of the size bytes.

Convert RGBA to Hex or ARGB to Hex

I am trying to convert a decimal colour code from a Flash Application into a hexadecimal colour code for HTML display
I have these numbers which are 8 digits long, but I am not sure if they are ARGB or RGBA. Is there a way to figure this out from the colour codes themselves?
I have a javascript function that can convert a decimal to a hexadecimal number but I am not compensating for the A value(or removing it). Can you help me fix my function to extract/remove the A value from the RGB decimal code?
function decimalToHex( num )
{
if (num == null || num == "undefined") { return "0xFFFFFF"; }
var intNum = (parseInt(num,10)) & 8; // does this remove the most significant 8 bits?
return intNum.toString(16);
}
If the alpha value is in the highest byte, then bitwise AND with 0x00FFFFFF to remove that. So:
var intNum = (parseInt(num,10)) & 0x00FFFFFF;
Or, if the alpha value is in the lowest byte, bitwise AND with 0xFFFFFF00, then shift right 8:
var intNum = (parseInt(num,10) & 0xFFFFFF00) >> 8;

Strange javascript operator: expr >>> 0 [duplicate]

This question already has answers here:
What is the JavaScript >>> operator and how do you use it?
(7 answers)
Closed 7 years ago.
the following function is designed to implement the indexOf property in IE. If you've ever had to do this, I'm sure you've seen it before.
if (!Array.prototype.indexOf){
Array.prototype.indexOf = function(elt, from){
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++){
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
I'm wondering if it's common to use three greater than signs as the author has done in the initial length check?
var len = this.length >>> 0
Doing this in a console simply returns the length of the object I pass to it, not true or false, which left me pondering the purpose of the syntax. Is this some high-level JavaScript Ninja technique that I don't know about? If so, please enlighten me!
>>> is the Zero-fill right shift operator. The >>> 0 is an abuse of the operator to convert any numeric expression to an "integer" or non-numeric expression to zero. Here is what it does:
This operator shifts the first operand the specified number of bits to
the right. Excess bits shifted off to the right are discarded. Zero
bits are shifted in from the left. The sign bit becomes 0, so the
result is always positive.
Here is an explanation of the convert-to-integer behavior which applies to all bitwise operations:
Bitwise operators treat their operands as a sequence of 32 bits (zeros
and ones), rather than as decimal, hexadecimal, or octal numbers.
[...] Bitwise operators perform their operations on such binary
representations, but they return standard JavaScript numerical values.
Together, these statements assert that expr >>> 0 will always return a positive number as follows:
expr is cast to a 32-bit integer for bitwise operation
>>> 0 has no effect (no bits are shifted)
The result is converted to a Number
Here are a few expressions and their outcome:
1 >>> 0 // 1 -- Number cast to 32-bit integer then back to Number
"1" >>> 0 // 1 -- String cast to 32-bit integer then back to Number
undefined >>> 0 // 0 -- failed cast yields zero
Other interesting cases:
1.1 >>> 0 // 1 -- decimal portion gets it
-1 >>> 0 // 4294967295 -- -1 = 0xFFFFFFFF
// Number(0xFFFFFFFF) = 4294967295
"A" >>> 0 // 0 -- cast failed
"1e2" >>> 0 // 100 -- 1x10^2 is 100
"1e10" >>> 0 // 1410065408 -- 1x10^10 is 10000000000
// 10000000000 is 0x00000002540BE400
// 32 bits of that number is 0x540BE400
// Number(0x540BE400) is 1410065408
Note: you will notice that none of them return NaN.
Source: LINK
This is the zero-fill right shift
operator which shifts the binary
representation of the first operand to
the right by the number of places
specified by the second operand. Bits
shifted off to the right are discarded
and zeroes are added on to the left.
With a positive number you would get
the same result as with the
sign-propagating right shift operator,
but negative numbers lose their sign
becoming positive as in the next
example, which (assuming 'a' to be
-13) would return 1073741820:
Code:
result = a >>> b;
The >>> (right-shift) binary operator is simply shifting the right-most bits of a number a specified number of times, and padding with zeroes to the left.
Note: In the following examples, the number in braces after a number signals what base it's in. 2 is for binary, 10 for decimal.
For example, 4 >>> 1 would do:
4(10) = 100(2)
4(10) >>> 1(10) = 010(2) = 2(10)
shift once to the right
Other examples:
4(10) >>> 2(10) = 100(2) >>> 2(10) = 001(2) = 1(10)
10(10) >>> 4(10) = 1010(2) >>> 4(10) = 0000(2) = 0(10)
15(10) >>> 1(10) = 1111(2) >>> 1(10) = 0111(2) = 7
The way I remember it is to move the necessary amount of bits to the right, and then write the number. Like, in the last example, I simply moved everything to the right once, so the result is 0111.
Shifting 0 times does...nothing. No idea why it's there.
Behold the zero-fill right-shift operator.
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Bitwise_Operators

Categories

Resources