Conversion for Hex to Float - Big Endian (ABCD) in JS - javascript

I need to convert this hex "46b76833" to float, and I need to get this value 23476.1
I written a code to get hex and everything else but this step I don't know how to do, can someone help me? Thanks in advance!
I tried something like this but it doesn't work.
function hexToFloat(hex) {
var s = hex >> 31 ? -1 : 1;
var e = (hex >> 23) & 0xFF;
var rez = s * (hex & 0x7fffff | 0x800000) * 1.0 / Math.pow(2, 23) * Math.pow(2, (e - 127));
return rez
}

You're nearly there, we just need to convert the hex string to a number before we tranform to a float.
The MSB is the sign, the following 8 bits are the exponent, then the last 23 bits represent the fraction of the number.
This is an IEEE Single Precision floating point number, there are more details here
function hexStringToFloat(hexString) {
const hex = parseInt(hexString, 16);
const sign = hex >> 31 ? -1 : 1;
const exponent = (hex >> 23) & 0xFF;
return sign * (hex & 0x7fffff | 0x800000) * 1.0 / Math.pow(2, 23) * Math.pow(2, (exponent - 127));
}
console.log("Result:", hexStringToFloat("46b76833"));

Related

What does OR 0x80 do?

In Bitwise operation, what does | 0x80 do? I know (& 0xFF) is convert value to 8 bit integer but how about (| 0x80) ?
I have the following code:
const buf = createHash('sha256').update('test').digest()
for (let i = 0; i < n; i++) {
const ubyte = buf.readUInt8(i)
const shifted = (ubyte >> 1) | mask
destBuf.writeUInt8(shifted, i)
mask = (ubyte & 1) * 0x80 // mask is 0 or 128
}
Can anyone explain that for me?
0x... means that what comes next is an hexadecimal number.
0x80 is the hexadecimal representation of the number 128. In binary, this equals 10000000.
The | character is the bitwise or operator. Suppose you have a 8-bit number:
a = xxxxxxxx
with x being either a 0 or a 1. Now, masking this number with 0x80 means:
xxxxxxxx | 10000000 = 1xxxxxxx
So it basically means you will have a 1 for your leftmost significant bit, while keeping all the other bits the same.
Now, in your code you use this mask in the line:
const shifted = (ubyte >> 1) | mask
What this does is takes the number ubyte:
ubyte = xxxxxxxy // x and y can be either 1 or 0
It shifts it right by onw digit:
ubyte >> 1 = zxxxxxxx // y gets lost, and z is a 0 if ubyte was unsigned.
Now it masks this number with your mask. When the mask is 128, the result is:
(ubyte >> 1) | 10000000 = 1xxxxxxx
So you will have a 1 as your most significant bit, and the other bits are unchanged.
It combines the bits of both participating numbers with the logical "or":
const b= 0x7;
function tst(a,b){
console.log(a.toString(2).padStart(8)+" first number: "+a)
console.log(b.toString(2).padStart(8)+" second number: "+b)
console.log((a | b).toString(2).padStart(8)+" bitwise overlay: "+(a|b))
console.log("----")
}
[0x80,0x6A,0x70,0x8f].forEach(a=>tst(a,b))

From hex to float - Javascript [duplicate]

This question already has answers here:
Converting hexadecimal to float in JavaScript
(9 answers)
Closed 5 years ago.
I am trying to convert a hex string to a float number in Javascript.
Suppose that I have the hex string "0082d241". Using this online converter and selecting Swap endianness, the correct float value is 26,3135.
I know that this is the correct answer because it is from a TMP36 sensor.
I have tried some other examples that I found here on SO, such as Converting hexadecimal to float in javascript, but none of them worked.
The first step is to swap endianness, using the source code found on the page that you've shown.
Then you can convert the hexadecimal string to a float value.
function flipHexString(hexValue, hexDigits) {
var h = hexValue.substr(0, 2);
for (var i = 0; i < hexDigits; ++i) {
h += hexValue.substr(2 + (hexDigits - 1 - i) * 2, 2);
}
return h;
}
function hexToFloat(hex) {
var s = hex >> 31 ? -1 : 1;
var e = (hex >> 23) & 0xFF;
return s * (hex & 0x7fffff | 0x800000) * 1.0 / Math.pow(2, 23) * Math.pow(2, (e - 127))
}
console.log(hexToFloat(flipHexString("0x0082d241", 8)));
console.log(hexToFloat(flipHexString("0x5d7e2842", 8)));

convert from a color back to a number in javascript

I have an existing fn that does the following:
public GetColor = (argb: number) => {
var a = 1;// (argb & -16777216) >> 0x18; // gives me FF
var r = (argb & 0xff0000) >> 0x10;
var g = (argb & 0x00ff00) >> 0x8;
var b = (argb & 0x0000ff);
var curKendoColor = kendo.parseColor("rgba(" + r + "," + g + "," + b + "," + a + ")", false);
I would like to know the function I would need to return that back to a number.
for example if i have AARRGGBB of (FFFF0000) and I would like to get back to the number version that toColor would have derived from.
I would be ok with the unsigned version of the return number or the signed version. Unsigned would be -65536 but the unsigned would be fine as well (not sure what that number would be off top of my head now)
I tried to do this but the attempts all end out at 0 which i know is not correct:
colorSend |= (parseInt(this.Color.substr(0,2),16) & 255) << 24;
colorSend |= (parseInt(this.Color.substr(1, 2), 16) & 255) << 16;
colorSend |= (parseInt(this.Color.substr(3, 2), 16) & 255) << 8;
the parseInt gives me the 255,0,0 that I think I would expect but the & and the shift logic does not seem correct because & zeros the integers out thus the result was 0
Ok I was able to get something that seems to work for me. I am simplifying it a bit but for the ARGB i can do something like
val = "0xFFFF0000"
val = parseInt(val, 16)
if((val & 0x80000000) != 0)
{
val = val - 0x100000000;
}
So for example for Red with an A of FF I would get-
-65536 or with unsigned I can omit the last part.
Actually it's pretty easy. You just have to understand what the HEX values mean.
In the hexadecimal system each number from 10 to 15 is represented by the letters A to F. The numbers lower ten are normal numbers 1 - 9. So if you want to convert 11 into hex it would be 0B. Because you need no number below 11 (0) and the letter B represents 11. If you read a little bit about the hex system, you should be able to write you new function very easily ;)

Javascript twos complement

The following python code seems to work very well to het the twos complement of a number:
def twos_comp(self, val, bits):
if (val & (1 << (bits - 1))) != 0:
val -= 1 << bits
return val
It is used as num = self.twos_comp(int(binStr, 2), len(binStr))
where binStr is a string that contains an arbitrary length binary number.
I need to do the exact same thing in javascript (for node.js). I've been fighting it all day and am about to resign from the human race. Clearly binary / bitwise math is not my strong suit.
Could someone please assist so I can go on to more productive time wasting :-)
function toTwosComplement(integer, numberBytes, dontCheckRange) {
// #integer - > the integer to convert
// #numberBytes -> the number of bytes representing the number (defaults to 1 if not specified)
var numberBits = (numberBytes || 1) * 8;
// make sure its in range given the number of bits
if (!dontCheckRange && (integer < (-(1 << (numberBits - 1))) || integer > ((1 << (numberBits - 1)) - 1)))
throw "Integer out of range given " + numberBytes + " byte(s) to represent.";
// if positive, return the positive value
if (integer >= 0)
return integer;
// if negative, convert to twos complement representation
return ~(((-integer) - 1) | ~((1 << numberBits) - 1));
}

Javascript: Parsing Double [duplicate]

I would like to convert a number in base 10 with fraction to a number in base 16.
var myno = 28.5;
var convno = myno.toString(16);
alert(convno);
All is well there. Now I want to convert it back to decimal.
But now I cannot write:
var orgno = parseInt(convno, 16);
alert(orgno);
As it doesn't return the decimal part.
And I cannot use parseFloat, since per MDC, the syntax of parseFloat is
parseFloat(str);
It wouldn't have been a problem if I had to convert back to int, since parseInt's syntax is
parseInt(str [, radix]);
So what is an alternative for this?
Disclaimer: I thought it was a trivial question, but googling didn't give me any answers.
This question made me ask the above question.
Another possibility is to parse the digits separately, splitting the string up in two and treating both parts as ints during the conversion and then add them back together.
function parseFloat(str, radix)
{
var parts = str.split(".");
if ( parts.length > 1 )
{
return parseInt(parts[0], radix) + parseInt(parts[1], radix) / Math.pow(radix, parts[1].length);
}
return parseInt(parts[0], radix);
}
var myno = 28.4382;
var convno = myno.toString(16);
var f = parseFloat(convno, 16);
console.log(myno + " -> " + convno + " -> " + f);
Try this.
The string may be raw data (simple text) with four characters (0 - 255) or
a hex string "0xFFFFFFFF" four bytes in length.
jsfiddle.net
var str = '0x3F160008';
function parseFloat(str) {
var float = 0, sign, order, mantissa, exp,
int = 0, multi = 1;
if (/^0x/.exec(str)) {
int = parseInt(str, 16);
}
else {
for (var i = str.length -1; i >=0; i -= 1) {
if (str.charCodeAt(i) > 255) {
console.log('Wrong string parameter');
return false;
}
int += str.charCodeAt(i) * multi;
multi *= 256;
}
}
sign = (int >>> 31) ? -1 : 1;
exp = (int >>> 23 & 0xff) - 127;
mantissa = ((int & 0x7fffff) + 0x800000).toString(2);
for (i=0; i<mantissa.length; i+=1) {
float += parseInt(mantissa[i]) ? Math.pow(2, exp) : 0;
exp--;
}
return float*sign;
}
Please try this:
function hex2dec(hex) {
hex = hex.split(/\./);
var len = hex[1].length;
hex[1] = parseInt(hex[1], 16);
hex[1] *= Math.pow(16, -len);
return parseInt(hex[0], 16) + hex[1];
}
function hex2dec(hex) {
hex = hex.split(/\./);
var len = hex[1].length;
hex[1] = parseInt(hex[1], 16);
hex[1] *= Math.pow(16, -len);
return parseInt(hex[0], 16) + hex[1];
}
// ----------
// TEST
// ----------
function calc(hex) {
let dec = hex2dec(hex);
msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(16)}</b>`
}
let init="bad.a55";
inp.value=init;
calc(init);
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>
I combined Mark's and Kent's answers to make an overloaded parseFloat function that takes an argument for the radix (much simpler and more versatile):
function parseFloat(string, radix)
{
// Split the string at the decimal point
string = string.split(/\./);
// If there is nothing before the decimal point, make it 0
if (string[0] == '') {
string[0] = "0";
}
// If there was a decimal point & something after it
if (string.length > 1 && string[1] != '') {
var fractionLength = string[1].length;
string[1] = parseInt(string[1], radix);
string[1] *= Math.pow(radix, -fractionLength);
return parseInt(string[0], radix) + string[1];
}
// If there wasn't a decimal point or there was but nothing was after it
return parseInt(string[0], radix);
}
Try this:
Decide how many digits of precision you need after the decimal point.
Multiply your original number by that power of 16 (e.g. 256 if you want two digits).
Convert it as an integer.
Put the decimal point in manually according to what you decided in step 1.
Reverse the steps to convert back.
Take out the decimal point, remembering where it was.
Convert the hex to decimal in integer form.
Divide the result by the the appropriate power of 16 (16^n, where n is the number of digits after the decimal point you took out in step 1).
A simple example:
Convert decimal 23.5 into hex, and want one digit after the decimal point after conversion.
23.5 x 16 = 376.
Converted to hex = 0x178.
Answer in base 16: 17.8
Now convert back to decimal:
Take out the decimal point: 0x178
Convert to decimal: 376
Divide by 16: 23.5
I'm not sure what hexadecimal format you wanted to parse there. Was this something like: "a1.2c"?
Floats are commonly stored in hexadecimal format using the IEEE 754 standard. That standard doesn't use any dots (which don't exist in pure hexadecimal alphabet). Instead of that there are three groups of bits of predefined length (1 + 8 + 23 = 32 bits in total ─ double uses 64 bits).
I've written the following function for parsing such a numbers into float:
function hex2float(num) {
var sign = (num & 0x80000000) ? -1 : 1;
var exponent = ((num >> 23) & 0xff) - 127;
var mantissa = 1 + ((num & 0x7fffff) / 0x7fffff);
return sign * mantissa * Math.pow(2, exponent);
}
Here is a size-improvement of Mark Eirich's answer:
function hex2dec(hex) {
let h = hex.split(/\./);
return ('0x'+h[1])*(16**-h[1].length)+ +('0x'+h[0]);
}
function hex2dec(hex) {
let h = hex.split(/\./);
return ('0x'+h[1])*(16**-h[1].length)+ +('0x'+h[0]);
}
function calc(hex) {
let dec = hex2dec(hex);
msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(16)}</b>`
}
let init = "bad.a55";
inp.value = init;
calc(init);
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>
private hexStringToFloat(hexString: string): number {
return Buffer.from(hexString, 'hex').readFloatBE(0);
}
Someone might find this useful.
bytes to Float32
function Int2Float32(bytes) {
var sign = (bytes & 0x80000000) ? -1 : 1;
var exponent = ((bytes >> 23) & 0xFF) - 127;
var significand = (bytes & ~(-1 << 23));
if (exponent == 128)
return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);
if (exponent == -127) {
if (significand === 0) return sign * 0.0;
exponent = -126;
significand /= (1 << 22);
} else significand = (significand | (1 << 23)) / (1 << 23);
return sign * significand * Math.pow(2, exponent);
}

Categories