Related
I have tried this
function binToDec(num) {
let dec = 0;
for(let i = 0; i < num.length; i++) {
if(num[num.length - (i + 1)] === '1') {
dec += 2 ** i;
}
}
return dec;
}
console.log(binToDec('1010'));
this code is not mine and it works but i want to know how it converts the binary number to decimal and it will be very helpful is you could tell me another way to do it.
I have also tried this
function binToDec(num) {
let bin = parseInt(num, 2);
return bin;
}
console.log(binToDec(1010));
I know this also work but i am not looking for this answer.
thank you for your help.
I just starts with the last character of the string and adds the value of this position to the result.
string dec
------ -------
1010 0
0 0
1 0 + 2
0 2
1 2 + 8
------ ------
10
function binToDec(num) {
let dec = 0;
for (let i = 0; i < num.length; i++) {
if (num[num.length - (i + 1)] === '1') {
dec += 2 ** i;
}
}
return dec;
}
console.log(binToDec('1010')); // 10
Another way is to start with the left side of the sting and
multiply the converted value by the base (2) and
add the value of the string.
The result is now the converted number. This works for all bases, as long as the value at the index is converted to a number.
function binToDec(num) {
let dec = 0;
for (let i = 0; i < num.length; i++) {
dec *= 2;
dec += +num[i];
}
return dec;
}
console.log(binToDec('1101')); // 13
Explanation
Think of how base 10 works.
909 = 900 + 9
= (9 * 100) + (0 * 10) + (9 * 1)
= (9 * 10**2) + (0 * 10**1) + (9 * 10**0)
As you can see, a natural number in base 10 can be seen as a sum where each term is in the form of:
digit * base**digit_position
This is true for any base:
base 2 : 0b101 = (0b1 * 2**2) + (0b0 * 2**1) + (0b1 * 2**0)
base 16 : 0xF0F = (0xF * 16**2) + (0x0 * 16**1) + (0xF * 16**0)
Therefore, here is a possible abstraction of a natural number:
function natural_number (base, digits) {
var sum = 0;
for (var i = 0; i < digits.length; i++) {
digit = digits[i];
digit_position = digits.length - (i + 1);
sum += digit * base**digit_position;
}
return sum;
}
> | natural_number(2, [1, 0, 1]) // 1 * 2**2 + 1 * 2**0
< | 5
> | natural_number(10, [1, 0, 1]) // 1 * 10**2 + 1 * 10**0
< | 101
> | natural_number(16, [1, 0, 1]) // 1 * 16**2 + 1 * 16**0
< | 257
Your own function takes only binary numbers (base 2). In this case digit can be either 0 or 1, that's all. We know that it's useless to multiply something by 0 or 1, so the addition can be replaced with:
if (digit === 1) {
sum += 2**digit_position;
}
Which is the equivalent of:
if (num[num.length - (i + 1)] === '1') {
dec += 2 ** i;
}
Do you get it? :-)
Alternative
You don't feel confortable with the exponentiation operator (**)? There is a workaround. Did you ever notice that multiplying a number by 10 is nothing more than shifting its digits one time to the left?
909 * 10 = 9090
Actually, shifting a number to the left boils down to multiplying this number by its base:
number *= base
This is true for any base:
base 2 : 0b11 * 2 = 0b110
base 16 : 0xBEE * 16 + 0xF = 0xBEE0 + 0xF = 0xBEEF
Based on this, we can build an algorithm to convert an array of digits into a number. A trace of execution with [9,0,9] in base 10 as input would look like this:
init | 0 | n = 0
add 9 | 9 | n += 9
shift | 90 | n *= 10
add 0 | 90 | n += 0
shift | 900 | n *= 10
add 9 | 909 | n += 9
Here is a possible implementation:
function natural_number (base, digits) {
var n = 0;
for (var i = 0; i < digits.length; i++) {
n += digits[i];
if (i + 1 < digits.length) {
n *= base;
}
}
return n;
}
Of course this function works the same as before, and there is a good reason for that. Indeed, unroll the for loop that computes [9,0,9] in base 10, you get this:
return ((0 + 9) * 10 + 0) * 10 + 9;
Then expand this expression:
((0 + 9) * 10 + 0) * 10 + 9
= (0 + 9) * 10 * 10 + 0 * 10 + 9
= 9 * 10 * 10 + 0 * 10 + 9
= 9 * 10**2 + 0 * 10**1 + 9 * 10**0
Do you recognize the equation discussed earlier? :-)
Bonus
Reverse function:
function explode_natural_number (base, number) {
var remainder, exploded = [];
while (number) {
remainder = number % base;
exploded.unshift(remainder);
number = (number - remainder) / base;
}
return exploded.length ? exploded : [0];
}
> | explode_natural_number(2, 5)
< | [1, 0, 1]
> | explode_natural_number(3, 5) // base 3 (5 = 1 * 3**1 + 2 * 3**0) :-)
< | [1, 2]
> | explode_natural_number(16, natural_number(16, [11, 14, 14, 15])) // 0xBEEF
< | [11, 14, 14, 15]
String to number and number to string:
function parse_natural_number (number, base) {
var ZERO = 48, A = 65; // ASCII codes
return natural_number(base, number.split("").map(function (digit) {
return digit.toUpperCase().charCodeAt(0);
}).map(function (code) {
return code - (code < A ? ZERO : A - 10);
}));
}
function stringify_natural_number (number, base) {
var ZERO = 48, A = 65; // ASCII codes
return String.fromCharCode.apply(
String, explode_natural_number(base, number).map(function (digit) {
return digit + (digit < 10 ? ZERO : A - 10);
})
);
}
> | stringify_natural_number(parse_natural_number("48879", 10), 16)
< | "BEEF"
> | parse_natural_number("10", 8)
< | 8
More levels of abstraction for convenience:
function bin_to_dec (number) {
return parse_natural_number(number, 2);
}
function oct_to_dec (number) {
return parse_natural_number(number, 8);
}
function dec_to_dec (number) {
return parse_natural_number(number, 10);
}
function hex_to_dec (number) {
return parse_natural_number(number, 16);
}
function num_to_dec (number) {
switch (number[0] + number[1]) {
case "0b" : return bin_to_dec(number.slice(2));
case "0x" : return hex_to_dec(number.slice(2));
default : switch (number[0]) {
case "0" : return oct_to_dec(number.slice(1));
default : return dec_to_dec(number);
}
}
}
> | oct_to_dec("10")
< | 8
> | num_to_dec("010")
< | 8
> | 010 // :-)
< | 8
function dec_to_bin (number) {
return stringify_natural_number(number, 2);
}
> | dec_to_bin(8)
< | "1000"
Is there any faster alternative to the following expression:
Math.pow(2,Math.floor(Math.log(x)/Math.log(2)))
That is, taking the closest (smaller) integer power of 2 of a double? I have such expression in a inner loop. I suspect it could be much faster, considering one could just take the mantissa from the IEEE 754 representation of the double.
Making use of ES6's Math.clz32(n) to count leading zeros of a 32-bit integer:
// Compute nearest lower power of 2 for n in [1, 2**31-1]:
function nearestPowerOf2(n) {
return 1 << 31 - Math.clz32(n);
}
// Examples:
console.log(nearestPowerOf2(9)); // 8
console.log(nearestPowerOf2(33)); // 32
Here's another alternative, with benchmarks. While both seems to be comparable, I like being able to floor or ceil.
function blpo2(x) {
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
x = x | (x >> 32);
return x - (x >> 1);
}
function pow2floor(v) {
var p = 1;
while (v >>= 1) {
p <<= 1;
}
return p;
}
function pow2ceil(v) {
var p = 2;
while (v >>= 1) {
p <<= 1;
}
return p;
}
function MATHpow2(v) {
return Math.pow(2, Math.floor(Math.log(v) / Math.log(2)))
}
function nearestPowerOf2(n) {
return 1 << 31 - Math.clz32(n);
}
function runner(fn, val) {
var res;
var st = new Date().getTime()
for (var i = 0; i < 100000000; i++) {
fn(val);
}
return (new Date().getTime() - st)
}
var source = 300000;
var a = runner(pow2floor, source);
console.log("\n--- pow2floor ---");
console.log(" result: " + pow2floor(source));
console.log(" time: " + a + " ms");
var b = runner(MATHpow2, source);
console.log("\n--- MATHpow2 ---");
console.log(" result: " + MATHpow2(source));
console.log(" time: " + b + " ms");
var b = runner(nearestPowerOf2, source);
console.log("\n--- nearestPowerOf2 ---");
console.log(" result: " + nearestPowerOf2(source));
console.log(" time: " + b + " ms");
var b = runner(blpo2, source);
console.log("\n--- blpo2 ---");
console.log(" result: " + blpo2(source));
console.log(" time: " + b + " ms");
// pow2floor: 1631 ms
// MATHpow2: 13942 ms
// nearestPowerOf2: 937 ms
// blpo2 : 919 ms **WINNER**
Here is also a branchless 32 bit version which is the fastest (9x) (on cellphones even more!) as of now.
It can also be scaled to 64 or 128 bits adding 1 or two lines:
x = x | (x >> 64);
x = x | (x >> 128);
on my computer:
2097152,blpo2: 118 ms **FASTEST**
2097152,nearestPowerOf2: 973 ms
2097152,pow2floor: 2033 ms
on my phone:
2097152,blpo2: 216 ms **FASTEST**
2097152,nearestPowerOf2: 1259 ms
2097152,pow2floor: 2904 ms
function blpo2(x) {
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
x = x | (x >> 32);
return x - (x >> 1);
}
function pow2floor(v) {
var p = 1;
while (v >>= 1) {
p <<= 1;
}
return p;
}
function nearestPowerOf2(n) {
return 1 << 31 - Math.clz32(n);
}
function runner(fn, val) {
var res;
var st = new Date().getTime()
for (var i = 0; i < 100000000; i++) {
res = fn(val);
}
dt = new Date().getTime() - st;
return res + "," + fn.name + ": " + dt + " ms"
}
var source = 3000000;
console.log(runner(blpo2, source), "**FASTEST**")
console.log(runner(nearestPowerOf2, source))
console.log(runner(pow2floor, source))
Unfortunately, you would need an equivalent of the C function frexp. The best I've been able to find is in JSFiddle, and its code uses Math.pow.
There are a couple of alternatives you could benchmark, using real data, along with your current attempt:
Starting at 1.0, multiply repeatedly by 2.0 until it is greater than or equal to the input, then multiply by 0.5 until it is less than or equal to the input. You would need special handling for values at the ends of the double range.
Store an ascending value array of all the exact powers of two in the double range, and do a binary search.
The first one is likely to be fastest if your data is typically close to 1.0. The second one requires up to 11 conditional branches.
Without ES6...
x=Math.floor(Math.random()*500000); //for example
nearestpowerof2=2**(x.toString(2).length-1);
console.log(x,">>>",nearestpowerof2);
In other words: the result is 2 to the power of the length of the binary representation of the number subtracted by 1.
And this is another.
function nP2(n) {
return 1 << Math.log2(n);
}
console.log(nP2(345367));
console.log(nP2(34536));
console.log(nP2(3453));
console.log(nP2(345));
console.log(nP2(34));
And another way (this one is slow but it's fun to code recursive ones):
function calc(n, c) {
c = c || 0;
n = n >> 1;
return (n > 0) ? calc(n, c + 1) : 2 ** c;
}
console.log(calc(345367));
console.log(calc(34536));
console.log(calc(3453));
console.log(calc(345));
console.log(calc(34));
Oh and I forgot the one-liner:
a=3764537465
console.log(2**~~Math.log2(a))
In other words, here we raise 2 to the power of the rounded logarithm in base 2 of the number. But alas, this is 140 times slower than the winner: blpo2 https://stackoverflow.com/a/74916422/236062
How do I convert a byte array into a string?
I have found these functions that do the reverse:
function string2Bin(s) {
var b = new Array();
var last = s.length;
for (var i = 0; i < last; i++) {
var d = s.charCodeAt(i);
if (d < 128)
b[i] = dec2Bin(d);
else {
var c = s.charAt(i);
alert(c + ' is NOT an ASCII character');
b[i] = -1;
}
}
return b;
}
function dec2Bin(d) {
var b = '';
for (var i = 0; i < 8; i++) {
b = (d%2) + b;
d = Math.floor(d/2);
}
return b;
}
But how do I get the functions working the other way?
Thanks.
Shao
You need to parse each octet back to number, and use that value to get a character, something like this:
function bin2String(array) {
var result = "";
for (var i = 0; i < array.length; i++) {
result += String.fromCharCode(parseInt(array[i], 2));
}
return result;
}
bin2String(["01100110", "01101111", "01101111"]); // "foo"
// Using your string2Bin function to test:
bin2String(string2Bin("hello world")) === "hello world";
Edit: Yes, your current string2Bin can be written more shortly:
function string2Bin(str) {
var result = [];
for (var i = 0; i < str.length; i++) {
result.push(str.charCodeAt(i).toString(2));
}
return result;
}
But by looking at the documentation you linked, I think that the setBytesParameter method expects that the blob array contains the decimal numbers, not a bit string, so you could write something like this:
function string2Bin(str) {
var result = [];
for (var i = 0; i < str.length; i++) {
result.push(str.charCodeAt(i));
}
return result;
}
function bin2String(array) {
return String.fromCharCode.apply(String, array);
}
string2Bin('foo'); // [102, 111, 111]
bin2String(string2Bin('foo')) === 'foo'; // true
ES6 update
Now, string 'foo' also equals
String.fromCharCode(...[102, 111, 111])
Original answer
Simply apply your byte array to String.fromCharCode. For example
String.fromCharCode.apply(null, [102, 111, 111])
equals 'foo'.
MDN docs here.
Caveat: works for arrays shorter than 65535 - MDN docs here.
Try the new Text Encoding API:
// create an array view of some valid bytes
let bytesView = new Uint8Array([104, 101, 108, 108, 111]);
console.log(bytesView);
// convert bytes to string
// encoding can be specfied, defaults to utf-8 which is ascii.
let str = new TextDecoder().decode(bytesView);
console.log(str);
// convert string to bytes
// encoding can be specfied, defaults to utf-8 which is ascii.
let bytes2 = new TextEncoder().encode(str);
// look, they're the same!
console.log(bytes2);
console.log(bytesView);
This should work:
String.fromCharCode(...array);
Or
String.fromCodePoint(...array)
That string2Bin can be written even more succinctly, and without any loops, to boot!
function string2Bin ( str ) {
return str.split("").map( function( val ) {
return val.charCodeAt( 0 );
} );
}
String to byte array: "FooBar".split('').map(c => c.charCodeAt(0));
Byte array to string: [102, 111, 111, 98, 97, 114].map(c => String.fromCharCode(c)).join('');
I think this would be more efficient:
function toBinString (arr) {
var uarr = new Uint8Array(arr.map(function(x){return parseInt(x,2)}));
var strings = [], chunksize = 0xffff;
// There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want
for (var i=0; i*chunksize < uarr.length; i++){
strings.push(String.fromCharCode.apply(null, uarr.subarray(i*chunksize, (i+1)*chunksize)));
}
return strings.join('');
}
Even if I'm a bit late, I thought it would be interesting for future users to share some one-liners implementations I did using ES6.
One thing that I consider important depending on your environment or/and what you will do with with the data is to preserve the full byte value. For example, (5).toString(2) will give you 101, but the complete binary conversion is in reality 00000101, and that's why you might need to create a leftPad implementation to fill the string byte with leading zeros. But you may not need it at all, like other answers demonstrated.
If you run the below code snippet, you'll see the first output being the conversion of the abc string to a byte array and right after that the re-transformation of said array to it's corresponding string.
// For each byte in our array, retrieve the char code value of the binary value
const binArrayToString = array => array.map(byte => String.fromCharCode(parseInt(byte, 2))).join('')
// Basic left pad implementation to ensure string is on 8 bits
const leftPad = str => str.length < 8 ? (Array(8).join('0') + str).slice(-8) : str
// For each char of the string, get the int code and convert it to binary. Ensure 8 bits.
const stringToBinArray = str => str.split('').map(c => leftPad(c.charCodeAt().toString(2)))
const array = stringToBinArray('abc')
console.log(array)
console.log(binArrayToString(array))
If your array is encoded in UTF-8 and you can't use the TextDecoder API because it is not supported on IE:
You can use the FastestSmallestTextEncoderDecoder polyfill recommended by the Mozilla Developer Network website;
You can use this function also provided at the MDN website:
function utf8ArrayToString(aBytes) {
var sView = "";
for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
nPart = aBytes[nIdx];
sView += String.fromCharCode(
nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
/* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */
(nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
(nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
(nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
(nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
(nPart - 192 << 6) + aBytes[++nIdx] - 128
: /* nPart < 127 ? */ /* one byte */
nPart
);
}
return sView;
}
let str = utf8ArrayToString([50,72,226,130,130,32,43,32,79,226,130,130,32,226,135,140,32,50,72,226,130,130,79]);
// Must show 2H₂ + O₂ ⇌ 2H₂O
console.log(str);
If you are using node.js you can do this:
yourByteArray.toString('base64');
Too late to answer but if your input is in form of ASCII bytes, then you could try this solution:
function convertArrToString(rArr){
//Step 1: Convert each element to character
let tmpArr = new Array();
rArr.forEach(function(element,index){
tmpArr.push(String.fromCharCode(element));
});
//Step 2: Return the string by joining the elements
return(tmpArr.join(""));
}
function convertArrToHexNumber(rArr){
return(parseInt(convertArrToString(rArr),16));
}
I had some decrypted byte arrays with padding characters and other stuff I didn't need, so I did this (probably not perfect, but it works for my limited use)
var junk = String.fromCharCode.apply(null, res).split('').map(char => char.charCodeAt(0) <= 127 && char.charCodeAt(0) >= 32 ? char : '').join('');
> const stringToBin = (str) => [...str].map(item=>item.charCodeAt())
> undefined
> stringToBin('hello')
> (5) [104, 101, 108, 108, 111]
> const binToString = (array) => String.fromCharCode(...array)
> undefined
> binToString(stringToBin('hello'))
> 'hello'
What you are looking for is String.fromCharCode
What you want to do is loop through the array of bytes (represented as integers), create the string equivalent and add it to the result:
function bin2String(array) {
var result = "";
for (const char of array) {
result += String.fromCharCode(char);
}
return result;
}
console.log(bin2String([116, 104, 101, 32, 114, 101, 115, 117, 108, 116]));
You can also use the Array.Map function to convert the array of bytes into an array of strings, then join them all.
function string2Bin(array) {
return array.map(byte => String.fromCharCode(byte)).join("");
}
console.log(string2Bin([116, 104, 101, 32, 114, 101, 115, 117, 108, 116]));
UPDATE
#rosberg-linhares posted best solution so far to handle UTF8.
Didn't find any solution that would work with UTF-8 characters. String.fromCharCode is good until you meet 2 byte character.
For example word Hüser can come over the wire in form of arraybuffer as [0x48,0xc3,0xbc,0x73,0x65,0x72] (e.g. through websocket connection)
But if you go through it with String.fromCharCode you will have Hüser as each byte will be converted to a char separately, and letter ü is encoded in two bytes.
Solution
Currently I'm using following solution:
function pad(n) { return (n.length < 2 ? '0' + n : n); }
function decodeUtf8(data) {
return decodeURIComponent(
data.map(byte => ('%' + pad(byte.toString(16)))).join('')
);
}
The simplest solution I've found is:
var text = atob(byteArray);
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);
}
I am trying in javascript to convert an integer (which I know will be between 0 and 32), to an array of 0s and 1s. I have looked around but couldn't find something that works..
So, if I have an integer as 22 (binary 10110), I would like to access it as:
Bitarr[0] = 0
Bitarr[1] = 1
Bitarr[2] = 1
Bitarr[3] = 0
Bitarr[4] = 1
Any suggestions?
Many thanks
convert to base 2:
var base2 = (yourNumber).toString(2);
access the characters (bits):
base2[0], base2[1], base2[3], etc...
Short (ES6)
Shortest (32 chars) version which fill last bits by zero. I assume that n is your number, b is base (number of output bits):
[...Array(b)].map((x,i)=>n>>i&1)
let bits = (n,b=32) => [...Array(b)].map((x,i)=>(n>>i)&1);
let Bitarr = bits(22,8);
console.log(Bitarr[0]); // = 0
console.log(Bitarr[1]); // = 1
console.log(Bitarr[2]); // = 1
console.log(Bitarr[3]); // = 0
console.log(Bitarr[4]); // = 1
var a = 22;
var b = [];
for (var i = 0; i < 5; i++)
b[i] = (a >> i) & 1;
alert(b);
Assuming 5 bits (it seemed from your question), so 0 <= a < 32. If you like you can make the 5 larger, upto 32 (bitshifting in JavaScript works with 32 bit integer).
This should do
for(int i = 0; i < 32; ++i)
Bitarr[i] = (my_int >> i) & 1;
You can convert your integer to a binary String like this. Note the base 2 parameter.
var i = 20;
var str = i.toString(2); // 10100
You can access chars in a String as if it were an array:
alert(str[0]); // 1
alert(str[1]); // 0
etc...
Building up on previous answers: you may want your array to be an array of integers, not strings, so here is a one-liner:
(1234).toString(2).split('').map(function(s) { return parseInt(s); });
Note, that shorter version, (11).toString(2).split('').map(parseInt) will not work (chrome), for unknown to me reason it converts "0"s to NaNs
In addition, this code gives 32length array
function get_bits(value){
var base2_ = (value).toString(2).split("").reverse().join("");
var baseL_ = new Array(32 - base2_.length).join("0");
var base2 = base2_ + baseL_;
return base2;
}
1 => 1000000000000000000000000000000
2 => 0100000000000000000000000000000
3 => 1100000000000000000000000000000
You might do as follows;
var n = 1071,
b = Array(Math.floor(Math.log2(n))+1).fill()
.map((_,i,a) => n >> a.length-1-i & 1);
console.log(b);
just for the sake of refernce:
(121231241).toString(2).split('').reverse().map((x, index) => x === '1' ? 1 << index : 0).reverse().filter(x => x > 0).join(' + ');
would give you:
67108864 + 33554432 + 16777216 + 2097152 + 1048576 + 524288 + 65536 + 32768 + 16384 + 4096 + 1024 + 512 + 256 + 128 + 8 + 1