Related
I am new to coding and javascript and was asked, for an assignment, to convert base 10 numbers to a binary base without using specific Javascript built in methods (like alert(a.toString(16))), and I am only allowed to use loops,arrays and functions. This is what i have so far:
var number = prompt("Enter an unsigned base 10 number");
if (number>=0) {
var base = prompt("Enter b for binary, o for octal, or h for hexadecimal");
if (base=="h"||base=="H") {
;
}
So as you can see, I don't have much to go on. I was curious as to what equation or formula I would use to convert the base 10 number, as well as how i'm supposed to show A=10, B=11, C=12 and so forth for a hexadecimal base. Any help would be greatly appreciated!
edit: This is a rather complicated way to do it,
as Alnitak showed me (see discussion below).
It is more a scibble, or the long way by foot.
Short explanation:
If we want to get the binary of the decimal number 10,
we have to try 2^n so that 2^n is still smaller than 10.
For example 2^3 = 8 (that is OK). But 2^4 = 16 (thats too big).
So we have 2^3 and store a 1 for that in an array at index 3.
Now we have to get the rest of 10-2^3, which is 2, and have to
make the same calculation again until we get a difference of zero.
At last we have to reverse the array because its the other way arround.
var a = prompt("Enter an unsigned base 10 number");
var arr = [];
var i = 0;
function decToBin(x) {
y = Math.pow(2, i);
if (y < x) {
arr[i] = 0;
i++;
decToBin(x);
} else if (y > x) {
i--;
newX = (x - Math.pow(2, i));
arr[i] = 1;
i = 0;
decToBin(newX)
} else if (y == x) {
arr[i] = 1;
result = arr.reverse().join();
}
return result;
}
var b = decToBin(a); // var b holds the result
document.write(b);
I have a 64 bit unsigned integer I need to represent in PostgreSQL. I've broken it down into two 32 bit unsigned integers, high and low. To allow Postgres to accept it, I need to convert high and low to a string representing a signed 64 bit integer.
How can I go about converting two 32 bit unsigned integers to a string representing in decimal a signed 64 bit integer?
I've done exactly this in Javascript in a quick'n'dirty-but-works'n'fast manner at: Int64HighLowToFromString, using 53-bit mantissa double precision arithmetic and 32-bit bit operations, specialized for decimal input/output.
function Int64HiLoToString(hi,lo){
hi>>>=0;lo>>>=0;
var sign="";
if(hi&0x80000000){
sign="-";
lo=(0x100000000-lo)>>>0;
hi=0xffffffff-hi+ +(lo===0);
}
var dhi=~~(hi/0x5af4),dhirem=hi%0x5af4;
var dlo=dhirem*0x100000000+dhi*0xef85c000+lo;
dhi += ~~(dlo/0x5af3107a4000);
dlo%=0x5af3107a4000;
var slo=""+dlo;
if(dhi){
slo="000000000000000000".slice(0,14-slo.length)+dlo;
return sign+dhi+slo;
}else{
return sign+slo;
}
}
Most likely this is what you needed.
I adapted the base conversion code from https://codegolf.stackexchange.com/questions/1620/arbitrary-base-conversion. Mistakes are mine, clevernesses are theirs.
I also had to add a bunch of code to deal with negative numbers (twos complement).
This code is ecmascript5, and will need slight reworking to work in older browsers.
function convert(hi, lo) {
function invertBit(bit) {
return bit == "0" ? "1" : "0";
}
function binaryInvert(binaryString) {
return binaryString.split("").map(invertBit).join("");
}
function binaryIncrement(binaryString) {
var idx = binaryString.lastIndexOf("0");
return binaryString.substring(0, idx) + "1" + binaryInvert(binaryString.substring(idx + 1));
}
function binaryDecrement(binaryString) {
var idx = binaryString.lastIndexOf("1");
return binaryString.substring(0, idx) + binaryInvert(binaryString.substring(idx));
}
function binaryAbs(binaryString) {
if (binaryString[0] === "1") {
return invertBits(binaryDecrement(binaryString));
}
return binaryString;
}
function to32Bits(val) {
var binaryString = val.toString(2);
if (binaryString[0] === "-") {
binaryString = Array(33 - (binaryString.length - 1)).join("1") + binaryInvert(binaryString.substr(1));
return binaryIncrement(binaryString);
}
return Array(33 - binaryString.length).join("0") + binaryString;
}
var fullBinaryNumber = to32Bits(hi) + to32Bits(lo);
var isNegative = fullBinaryNumber[0] === "1";
fullBinaryNumber = binaryAbs(fullBinaryNumber);
var result = "";
while (fullBinaryNumber.length > 0) {
var remainingToConvert = "", resultDigit = 0;
for (var position = 0; position < fullBinaryNumber.length; ++position) {
var currentValue = Number(fullBinaryNumber[position]) + resultDigit * 2;
var remainingDigitToConvert = Math.floor(currentValue / 10);
resultDigit = currentValue % 10;
if (remainingToConvert.length || remainingDigitToConvert) {
remainingToConvert += remainingDigitToConvert;
}
}
fullBinaryNumber = remainingToConvert;
result = resultDigit + result;
}
return (isNegative?"-":"") + result;
}
Examples:
> // largest negative number -2^63 (just the most significant bit set)
> convert(1 << 31, 0)
'-9223372036854775808'
> // largest positive number
> convert(0x7fffffff, 0xffffffff)
'9223372036854775807'
> // -1 is all bits set.
> convert(0xffffffff, 0xffffffff)
'-1'
According to JavaScript can't handle 64-bit integers, can it?, native numbers in Javascript have 53 bits of mantissa, so JS can't deal with 64 bits integers unless using specialized libraries.
Whatever the datatype and implementation limits, I assume you want to compute the Two's complement of the initial 64 bits unsigned number, to convert it from the [0 ... 2^64-1] range into the [-2^63 ... 2^63-1] range.
high is presumably the initial unsigned 64 bits number divided by 2^32, and low is the remainder.
The conversion to a signed 64 bits should go like this:
if high>=2^63 then
s64 = -(2^64-(high*2^32+low))
else
s64 = high*2^32+low;
In a PostgreSQL function, this can be done using the exact-precision numeric type to avoid overflows in intermediate multiplications, and downcast the final result to bigint (signed 64 bits):
create function concat64(bigint, bigint) returns bigint
as $$
select (case when $1>=2147483648
then -(18446744073709551616::numeric-($1*4294967296::numeric+$2))
else $1*4294967296::numeric+$2 end)::bigint;
$$ language sql;
The input arguments have to be bigint (64 bits) because postgres doesn't have unsigned types.
They're assumed to be in the [0..4294967296] range and the output should be in the [-9223372036854775808..9223372036854775807] range.
So, to be short,
3√(-8) = (-8)1/3
console.log(Math.pow(-8,1/3));
//Should be -2
But when I test it out, it outputs
NaN
Why? Is it a bug or it is expected to be like this in the first place? I am using JavaScript to draw graphs, but this messes up the graph.
You can use this snippet to calculate it. It also works for other powers, e.g. 1/4, 1/5, etc.
function nthroot(x, n) {
try {
var negate = n % 2 == 1 && x < 0;
if(negate)
x = -x;
var possible = Math.pow(x, 1 / n);
n = Math.pow(possible, n);
if(Math.abs(x - n) < 1 && (x > 0 == n > 0))
return negate ? -possible : possible;
} catch(e){}
}
nthroot(-8, 3);
Source: http://gotochriswest.com/blog/2011/05/06/cube-root-an-beyond/
A faster approach for just calculating the cubic root:
Math.cbrt = function(x) {
var sign = x === 0 ? 0 : x > 0 ? 1 : -1;
return sign * Math.pow(Math.abs(x), 1 / 3);
}
Math.cbrt(-8);
Update
To find an integer based cubic root, you can use the following function, inspired by this answer:
// positive-only cubic root approximation
function cbrt(n)
{
var a = n; // note: this is a non optimized assumption
while (a * a * a > n) {
a = Math.floor((2 * a + (n / (a * a))) / 3);
}
return a;
}
It starts with an assumption that converges to the closest integer a for which a^3 <= n. This function can be adjusted in the same way to support a negative base.
There's no bug; you are raising a negative number to a fractional power; hence, the NaN.
The top hit on google for this is from Dr Math the explanation is pretty good. It says for for real numbers (not complex numbers anyway), a negative number raised to a fractional power may not be a real number. The simplest example is probably
-4 ^ (1/2)
which is essentially computing the square root of -4. Even though the cubic root of -8 does have real solutions, I think that most software libraries find it more efficient not to do all the complex arithmetic and return NaN only when the imaginary part is nonzero and give you the nice real answer otherwise.
EDIT
Just to make absolutely clear that NaN is the intended result, see the official ECMAScript 5.1 Specification, Section 15.8.2.13. It says:
If x<0 and x is finite and y is finite and y is not an integer, the result is NaN.
Again, even though SOME instances of raising negative numbers to fractional powers have exactly one real root, many languages just do the NaN thing for all cases of negative numbers to fractional roots.
Please do not think JavaScript is the only such language. C++ does the same thing:
If x is finite negative and y is finite but not an integer value, it causes a domain error.
Two key problems:
Mathematically, there are multiple cubic roots of a negative number: -2, but also 2 complex roots (see cube roots of unity).
Javascript's Math object (and most other standard math libraries) will not do fractional powers of negative numbers. It converts the fractional power to a float before the function receives it, so you are asking the function to compute a floating point power of a negative number, which may or may not have a real solution. So it does the pragmatic thing and refuses to attempt to calculate such a value.
If you want to get the correct answer, you'll need to decide how mathematically correct you want to be, and write those rules into a non-standard implementation of pow.
All library functions are limited to avoid excessive calculation times and unnecessary complexity.
I like the other answers, but how about overriding Math.pow so it would be able to work with all nth roots of negative numbers:
//keep the original method for proxying
Math.pow_ = Math.pow;
//redefine the method
Math.pow = function(_base, _exponent) {
if (_base < 0) {
if (Math.abs(_exponent) < 1) {
//we're calculating nth root of _base, where n === 1/_exponent
if (1 / _exponent % 2 === 0) {
//nth root of a negative number is imaginary when n is even, we could return
//a string like "123i" but this would completely mess up further computation
return NaN;
}/*else if (1 / _exponent % 2 !== 0)*/
//nth root of a negative number when n is odd
return -Math.pow_(Math.abs(_base), _exponent);
}
}/*else if (_base >=0)*/
//run the original method, nothing will go wrong
return Math.pow_(_base, _exponent);
};
Fiddled with some test cases, give me a shout if you spot a bug!
So I see a bunch of methods that revolve around Math.pow(...) which is cool, but based on the wording of the bounty I'm proposing a slightly different approach.
There are several computational approximations for solving roots, some taking quicker steps than others. Ultimately the stopping point comes down to the degree of precision desired(it's really up to you/the problem being solved).
I'm not going to explain the math in fine detail, but the following are implementations of cubed root approximations that passed the target test(bounty test - also added negative range, because of the question title). Each iteration in the loop (see the while(Math.abs(xi-xi0)>precision) loops in each method) gets a step closer to the desired precision. Once precision is achieved a format is applied to the number so it's as precise as the calculation derived from the iteration.
var precision = 0.0000000000001;
function test_cuberoot_fn(fn) {
var tested = 0,
failed = 0;
for (var i = -100; i < 100; i++) {
var root = fn(i*i*i);
if (i !== root) {
console.log(i, root);
failed++;
}
tested++;
}
if (failed) {
console.log("failed %d / %d", failed, tested);
}else{
console.log("Passed test");
}
}
test_cuberoot_fn(newtonMethod);
test_cuberoot_fn(halleysMethod);
Newton's approximation Implementation
function newtonMethod(cube){
if(cube == 0){//only John Skeet and Chuck Norris
return 0; //can divide by zero, we'll have
} //to settle for check and return
var xi = 1;
var xi0 = -1;
while(Math.abs(xi-xi0)>precision){//precision = 0.0000000000001
xi0=xi;
xi = (1/3)*((cube/(xi*xi))+2*xi);
}
return Number(xi.toPrecision(12));
}
Halley's approximation Implementation
note Halley's approximation takes quicker steps to solving the cube, so it's computationally faster than newton's approximation.
function halleysMethod(cube){
if(cube == 0){//only John Skeet and Chuck Norris
return 0; //can divide by zero, we'll have
} //to settle for check and return
var xi = 1;
var xi0 = -1;
while(Math.abs(xi-xi0)>precision){//precision = 0.0000000000001
xi0=xi;
xi = xi*((xi*xi*xi + 2*cube)/(2*xi*xi*xi+cube));
}
return Number(xi.toPrecision(12));
}
It's Working in Chrome Console
function cubeRoot(number) {
var num = number;
var temp = 1;
var inverse = 1 / 3;
if (num < 0) {
num = -num;
temp = -1;
}
var res = Math.pow(num, inverse);
var acc = res - Math.floor(res);
if (acc <= 0.00001)
res = Math.floor(res);
else if (acc >= 0.99999)
res = Math.ceil(res);
return (temp * res);
}
cubeRoot(-64) // -4
cubeRoot(64) // 4
As a heads up, in ES6 there is now a Math.cbrt function.
In my testing in Google chrome it appears to work almost twice as fast as Math.pow. Interestingly I had to add up the results otherwise chrome did a better job of optimizing away the pow function.
//do a performance test on the cube root function from es6
var start=0, end=0, k=0;
start = performance.now();
k=0;
for (var i=0.0; i<10000000.0; i+=1.0)
{
var j = Math.cbrt(i);
//k+=j;
}
end = performance.now();
console.log("cbrt took:" + (end-start),k);
k=0;
start = performance.now();
for (var i=0.0; i<10000000.0; i+=1.0)
{
var j = Math.pow(i,0.33333333);
//k+=j;
}
end = performance.now();
console.log("pow took:" + (end-start),k);
k=0;
start = performance.now();
for (var i=0.0; i<10000000.0; i+=1.0)
{
var j = Math.cbrt(i);
k+=j;
}
end = performance.now();
console.log("cbrt took:" + (end-start),k);
k=0;
start = performance.now();
for (var i=0.0; i<10000000.0; i+=1.0)
{
var j = Math.pow(i,0.33333333);
k+=j;
}
end = performance.now();
console.log("pow took:" + (end-start),k);
Result:
cbrt took:468.28200000163633 0
pow took:77.21999999921536 0
cbrt took:546.8039999977918 1615825909.5248165
pow took:869.1149999940535 1615825826.7510242
//aren't cube roots of negative numbers the same as positive, except for the sign?
Math.cubeRoot= function(n, r){
var sign= (n<0)? -1: 1;
return sign*Math.pow(Math.abs(n), 1/3);
}
Math.cubeRoot(-8)
/* returned value: (Number)
-2
*/
Just want to highlight that in ES6 there is a native cubic root function. So you can just do this (check the support here)
Math.cbrt(-8) will return you -2
this works with negative number and negative exponent:
function nthRoot(x = 0, r = 1) {
if (x < 0) {
if (r % 2 === 1) return -nthRoot(-x, r)
if (r % 2 === -1) return -1 / nthRoot(-x, -r)
}
return x ** (1 / r)
}
examples:
nthRoot( 16, 2) 4
nthRoot( 16, -2) 0.25
nthRoot(-16, 2) NaN
nthRoot(-16, -2) NaN
nthRoot( 27, 3) 3
nthRoot( 27, -3) 0.3333333333333333
nthRoot(-27, 3) -3
nthRoot(-27, -3) -0.3333333333333333
I’d like to see integers, positive or negative, in binary.
Rather like this question, but for JavaScript.
function dec2bin(dec) {
return (dec >>> 0).toString(2);
}
console.log(dec2bin(1)); // 1
console.log(dec2bin(-1)); // 11111111111111111111111111111111
console.log(dec2bin(256)); // 100000000
console.log(dec2bin(-256)); // 11111111111111111111111100000000
You can use Number.toString(2) function, but it has some problems when representing negative numbers. For example, (-1).toString(2) output is "-1".
To fix this issue, you can use the unsigned right shift bitwise operator (>>>) to coerce your number to an unsigned integer.
If you run (-1 >>> 0).toString(2) you will shift your number 0 bits to the right, which doesn't change the number itself but it will be represented as an unsigned integer. The code above will output "11111111111111111111111111111111" correctly.
This question has further explanation.
-3 >>> 0 (right logical shift) coerces its arguments to unsigned integers, which is why you get the 32-bit two's complement representation of -3.
Try
num.toString(2);
The 2 is the radix and can be any base between 2 and 36
source here
UPDATE:
This will only work for positive numbers, Javascript represents negative binary integers in two's-complement notation. I made this little function which should do the trick, I haven't tested it out properly:
function dec2Bin(dec)
{
if(dec >= 0) {
return dec.toString(2);
}
else {
/* Here you could represent the number in 2s compliment but this is not what
JS uses as its not sure how many bits are in your number range. There are
some suggestions https://stackoverflow.com/questions/10936600/javascript-decimal-to-binary-64-bit
*/
return (~dec).toString(2);
}
}
I had some help from here
A simple way is just...
Number(42).toString(2);
// "101010"
The binary in 'convert to binary' can refer to three main things. The positional number system, the binary representation in memory or 32bit bitstrings. (for 64bit bitstrings see Patrick Roberts' answer)
1. Number System
(123456).toString(2) will convert numbers to the base 2 positional numeral system. In this system negative numbers are written with minus signs just like in decimal.
2. Internal Representation
The internal representation of numbers is 64 bit floating point and some limitations are discussed in this answer. There is no easy way to create a bit-string representation of this in javascript nor access specific bits.
3. Masks & Bitwise Operators
MDN has a good overview of how bitwise operators work. Importantly:
Bitwise operators treat their operands as a sequence of 32 bits (zeros and ones)
Before operations are applied the 64 bit floating points numbers are cast to 32 bit signed integers. After they are converted back.
Here is the MDN example code for converting numbers into 32-bit strings.
function createBinaryString (nMask) {
// nMask must be between -2147483648 and 2147483647
for (var nFlag = 0, nShifted = nMask, sMask = ""; nFlag < 32;
nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
return sMask;
}
createBinaryString(0) //-> "00000000000000000000000000000000"
createBinaryString(123) //-> "00000000000000000000000001111011"
createBinaryString(-1) //-> "11111111111111111111111111111111"
createBinaryString(-1123456) //-> "11111111111011101101101110000000"
createBinaryString(0x7fffffff) //-> "01111111111111111111111111111111"
This answer attempts to address inputs with an absolute value in the range of 214748364810 (231) – 900719925474099110 (253-1).
In JavaScript, numbers are stored in 64-bit floating point representation, but bitwise operations coerce them to 32-bit integers in two's complement format, so any approach which uses bitwise operations restricts the range of output to -214748364810 (-231) – 214748364710 (231-1).
However, if bitwise operations are avoided and the 64-bit floating point representation is preserved by using only mathematical operations, we can reliably convert any safe integer to 64-bit two's complement binary notation by sign-extending the 53-bit twosComplement:
function toBinary (value) {
if (!Number.isSafeInteger(value)) {
throw new TypeError('value must be a safe integer');
}
const negative = value < 0;
const twosComplement = negative ? Number.MAX_SAFE_INTEGER + value + 1 : value;
const signExtend = negative ? '1' : '0';
return twosComplement.toString(2).padStart(53, '0').padStart(64, signExtend);
}
function format (value) {
console.log(value.toString().padStart(64));
console.log(value.toString(2).padStart(64));
console.log(toBinary(value));
}
format(8);
format(-8);
format(2**33-1);
format(-(2**33-1));
format(2**53-1);
format(-(2**53-1));
format(2**52);
format(-(2**52));
format(2**52+1);
format(-(2**52+1));
.as-console-wrapper{max-height:100%!important}
For older browsers, polyfills exist for the following functions and values:
Number.isSafeInteger()
Number.isInteger()
Number.MAX_SAFE_INTEGER
String.prototype.padStart()
As an added bonus, you can support any radix (2–36) if you perform the two's complement conversion for negative numbers in ⌈64 / log2(radix)⌉ digits by using BigInt:
function toRadix (value, radix) {
if (!Number.isSafeInteger(value)) {
throw new TypeError('value must be a safe integer');
}
const digits = Math.ceil(64 / Math.log2(radix));
const twosComplement = value < 0
? BigInt(radix) ** BigInt(digits) + BigInt(value)
: value;
return twosComplement.toString(radix).padStart(digits, '0');
}
console.log(toRadix(0xcba9876543210, 2));
console.log(toRadix(-0xcba9876543210, 2));
console.log(toRadix(0xcba9876543210, 16));
console.log(toRadix(-0xcba9876543210, 16));
console.log(toRadix(0x1032547698bac, 2));
console.log(toRadix(-0x1032547698bac, 2));
console.log(toRadix(0x1032547698bac, 16));
console.log(toRadix(-0x1032547698bac, 16));
.as-console-wrapper{max-height:100%!important}
If you are interested in my old answer that used an ArrayBuffer to create a union between a Float64Array and a Uint16Array, please refer to this answer's revision history.
A solution i'd go with that's fine for 32-bits, is the code the end of this answer, which is from developer.mozilla.org(MDN), but with some lines added for A)formatting and B)checking that the number is in range.
Some suggested x.toString(2) which doesn't work for negatives, it just sticks a minus sign in there for them, which is no good.
Fernando mentioned a simple solution of (x>>>0).toString(2); which is fine for negatives, but has a slight issue when x is positive. It has the output starting with 1, which for positive numbers isn't proper 2s complement.
Anybody that doesn't understand the fact of positive numbers starting with 0 and negative numbers with 1, in 2s complement, could check this SO QnA on 2s complement. What is “2's Complement”?
A solution could involve prepending a 0 for positive numbers, which I did in an earlier revision of this answer. And one could accept sometimes having a 33bit number, or one could make sure that the number to convert is within range -(2^31)<=x<2^31-1. So the number is always 32bits. But rather than do that, you can go with this solution on mozilla.org
Patrick's answer and code is long and apparently works for 64-bit, but had a bug that a commenter found, and the commenter fixed patrick's bug, but patrick has some "magic number" in his code that he didn't comment about and has forgotten about and patrick no longer fully understands his own code / why it works.
Annan had some incorrect and unclear terminology but mentioned a solution by developer.mozilla.org
Note- the old link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators now redirects elsewhere and doesn't have that content but the proper old link , which comes up when archive.org retrieves pages!, is available here https://web.archive.org/web/20150315015832/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
The solution there works for 32-bit numbers.
The code is pretty compact, a function of three lines.
But I have added a regex to format the output in groups of 8 bits. Based on How to format a number with commas as thousands separators? (I just amended it from grouping it in 3s right to left and adding commas, to grouping in 8s right to left, and adding spaces)
And, while mozilla made a comment about the size of nMask(the number fed in)..that it has to be in range, they didn't test for or throw an error when the number is out of range, so i've added that.
I'm not sure why they named their parameter 'nMask' but i'll leave that as is.
https://web.archive.org/web/20150315015832/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
function createBinaryString(nMask) {
// nMask must be between -2147483648 and 2147483647
if (nMask > 2**31-1)
throw "number too large. number shouldn't be > 2**31-1"; //added
if (nMask < -1*(2**31))
throw "number too far negative, number shouldn't be < -(2**31)" //added
for (var nFlag = 0, nShifted = nMask, sMask = ''; nFlag < 32;
nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
sMask=sMask.replace(/\B(?=(.{8})+(?!.))/g, " ") // added
return sMask;
}
console.log(createBinaryString(-1)) // "11111111 11111111 11111111 11111111"
console.log(createBinaryString(1024)) // "00000000 00000000 00000100 00000000"
console.log(createBinaryString(-2)) // "11111111 11111111 11111111 11111110"
console.log(createBinaryString(-1024)) // "11111111 11111111 11111100 00000000"
//added further console.log example
console.log(createBinaryString(2**31 -1)) //"01111111 11111111 11111111 11111111"
You can write your own function that returns an array of bits.
Example how to convert number to bits
Divisor| Dividend| bits/remainder
2 | 9 | 1
2 | 4 | 0
2 | 2 | 0
~ | 1 |~
example of above line: 2 * 4 = 8 and remainder is 1
so 9 = 1 0 0 1
function numToBit(num){
var number = num
var result = []
while(number >= 1 ){
result.unshift(Math.floor(number%2))
number = number/2
}
return result
}
Read remainders from bottom to top. Digit 1 in the middle to top.
This is how I manage to handle it:
const decbin = nbr => {
if(nbr < 0){
nbr = 0xFFFFFFFF + nbr + 1
}
return parseInt(nbr, 10).toString(2)
};
got it from this link: https://locutus.io/php/math/decbin/
we can also calculate the binary for positive or negative numbers as below:
function toBinary(n){
let binary = "";
if (n < 0) {
n = n >>> 0;
}
while(Math.ceil(n/2) > 0){
binary = n%2 + binary;
n = Math.floor(n/2);
}
return binary;
}
console.log(toBinary(7));
console.log(toBinary(-7));
You could use a recursive solution:
function intToBinary(number, res = "") {
if (number < 1)
if (res === "") return "0"
else
return res
else return intToBinary(Math.floor(number / 2), number % 2 + res)
}
console.log(intToBinary(12))
console.log(intToBinary(546))
console.log(intToBinary(0))
console.log(intToBinary(125))
Works only with positive numbers.
An actual solution that logic can be implemented by any programming language:
If you sure it is positive only:
var a = 0;
var n = 12; // your input
var m = 1;
while(n) {
a = a + n%2*m;
n = Math.floor(n/2);
m = m*10;
}
console.log(n, ':', a) // 12 : 1100
If can negative or positive -
(n >>> 0).toString(2)
I’d like to see integers, positive or negative, in binary.
This is an old question and I think there are very nice solutions here but there is no explanation about the use of these clever solutions.
First, we need to understand that a number can be positive or negative.
Also, JavaScript provides a MAX_SAFE_INTEGER constant that has a value of 9007199254740991. The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent integers between -(2^53 - 1) and 2^53 - 1.
So, now we know the range where numbers are "safe". Also, JavaScript ES6 has the built-in method Number.isSafeInteger() to check if a number is a safe integer.
Logically, if we want to represent a number n as binary, this number needs a length of 53 bits, but for better presentation lets use 7 groups of 8 bits = 56 bits and fill the left side with 0 or 1 based on its sign using the padStart function.
Next, we need to handle positive and negative numbers: positive numbers will add 0s to the left while negative numbers will add 1s. Also, negative numbers will need a two's-complement representation. We can easily fix this by adding Number.MAX_SAFE_INTEGER + 1 to the number.
For example, we want to represent -3 as binary, lets assume that Number.MAX_SAFE_INTEGER is 00000000 11111111 (255) then Number.MAX_SAFE_INTEGER + 1 will be 00000001 00000000 (256). Now lets add the number Number.MAX_SAFE_INTEGER + 1 - 3 this will be 00000000 11111101 (253) but as we said we will fill with the left side with 1 like this 11111111 11111101 (-3), this represent -3 in binary.
Another algorithm will be we add 1 to the number and invert the sign like this -(-3 + 1) = 2 this will be 00000000 00000010 (2). Now we invert every bit like this 11111111 11111101 (-3) again we have a binary representation of -3.
Here we have a working snippet of these algos:
function dec2binA(n) {
if (!Number.isSafeInteger(n)) throw new TypeError('n value must be a safe integer')
if (n > 2**31) throw 'number too large. number should not be greater than 2**31'
if (n < -1*(2**31)) throw 'number too far negative, number should not be lesser than 2**31'
const bin = n < 0 ? Number.MAX_SAFE_INTEGER + 1 + n : n
const signBit = n < 0 ? '1' : '0'
return parseInt(bin, 10).toString(2)
.padStart(56, signBit)
.replace(/\B(?=(.{8})+(?!.))/g, ' ')
}
function dec2binB(n) {
if (!Number.isSafeInteger(n)) throw new TypeError('n value must be a safe integer')
if (n > 2**31) throw 'number too large. number should not be greater than 2**31'
if (n < -1*(2**31)) throw 'number too far negative, number should not be lesser than 2**31'
const bin = n < 0 ? -(1 + n) : n
const signBit = n < 0 ? '1' : '0'
return parseInt(bin, 10).toString(2)
.replace(/[01]/g, d => +!+d)
.padStart(56, signBit)
.replace(/\B(?=(.{8})+(?!.))/g, ' ')
}
const a = -805306368
console.log(a)
console.log('dec2binA:', dec2binA(a))
console.log('dec2binB:', dec2binB(a))
const b = -3
console.log(b)
console.log('dec2binA:', dec2binA(b))
console.log('dec2binB:', dec2binB(b))
One more alternative
const decToBin = dec => {
let bin = '';
let f = false;
while (!f) {
bin = bin + (dec % 2);
dec = Math.trunc(dec / 2);
if (dec === 0 ) f = true;
}
return bin.split("").reverse().join("");
}
console.log(decToBin(0));
console.log(decToBin(1));
console.log(decToBin(2));
console.log(decToBin(3));
console.log(decToBin(4));
console.log(decToBin(5));
console.log(decToBin(6));
I used a different approach to come up with something that does this. I've decided to not use this code in my project, but I thought I'd leave it somewhere relevant in case it is useful for someone.
Doesn't use bit-shifting or two's complement coercion.
You choose the number of bits that comes out (it checks for valid values of '8', '16', '32', but I suppose you could change that)
You choose whether to treat it as a signed or unsigned integer.
It will check for range issues given the combination of signed/unsigned and number of bits, though you'll want to improve the error handling.
It also has the "reverse" version of the function which converts the bits back to the int. You'll need that since there's probably nothing else that will interpret this output :D
function intToBitString(input, size, unsigned) {
if ([8, 16, 32].indexOf(size) == -1) {
throw "invalid params";
}
var min = unsigned ? 0 : - (2 ** size / 2);
var limit = unsigned ? 2 ** size : 2 ** size / 2;
if (!Number.isInteger(input) || input < min || input >= limit) {
throw "out of range or not an int";
}
if (!unsigned) {
input += limit;
}
var binary = input.toString(2).replace(/^-/, '');
return binary.padStart(size, '0');
}
function bitStringToInt(input, size, unsigned) {
if ([8, 16, 32].indexOf(size) == -1) {
throw "invalid params";
}
input = parseInt(input, 2);
if (!unsigned) {
input -= 2 ** size / 2;
}
return input;
}
// EXAMPLES
var res;
console.log("(uint8)10");
res = intToBitString(10, 8, true);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");
console.log("(uint8)127");
res = intToBitString(127, 8, true);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");
console.log("(int8)127");
res = intToBitString(127, 8, false);
console.log("intToBitString(res, 8, false)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, false));
console.log("---");
console.log("(int8)-128");
res = intToBitString(-128, 8, false);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");
console.log("(uint16)5000");
res = intToBitString(5000, 16, true);
console.log("intToBitString(res, 16, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 16, true));
console.log("---");
console.log("(uint32)5000");
res = intToBitString(5000, 32, true);
console.log("intToBitString(res, 32, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 32, true));
console.log("---");
This is a method that I use. It's a very fast and concise method that works for whole numbers.
If you want, this method also works with BigInts. You just have to change each 1 to 1n.
// Assuming {num} is a whole number
function toBin(num){
let str = "";
do {
str = `${num & 1}${str}`;
num >>= 1;
} while(num);
return str
}
Explanation
This method, in a way, goes through all the bits of the number as if it's already a binary number.
It starts with an empty string, and then it prepends the last bit. num & 1 will return the last bit of the number (1 or 0). num >>= 1 then removes the last bit and makes the second-to-last bit the new last bit. The process is repeated until all the bits have been read.
Of course, this is an extreme simplification of what's actually going on. But this is how I generalize it.
This is my code:
var x = prompt("enter number", "7");
var i = 0;
var binaryvar = " ";
function add(n) {
if (n == 0) {
binaryvar = "0" + binaryvar;
}
else {
binaryvar = "1" + binaryvar;
}
}
function binary() {
while (i < 1) {
if (x == 1) {
add(1);
document.write(binaryvar);
break;
}
else {
if (x % 2 == 0) {
x = x / 2;
add(0);
}
else {
x = (x - 1) / 2;
add(1);
}
}
}
}
binary();
This is the solution . Its quite simple as a matter of fact
function binaries(num1){
var str = num1.toString(2)
return(console.log('The binary form of ' + num1 + ' is: ' + str))
}
binaries(3
)
/*
According to MDN, Number.prototype.toString() overrides
Object.prototype.toString() with the useful distinction that you can
pass in a single integer argument. This argument is an optional radix,
numbers 2 to 36 allowed.So in the example above, we’re passing in 2 to
get a string representation of the binary for the base 10 number 100,
i.e. 1100100.
*/
What I would like to have is the almost opposite of Number.prototype.toPrecision(), meaning that when i have number, how many decimals does it have? E.g.
(12.3456).getDecimals() // 4
For anyone wondering how to do this faster (without converting to string), here's a solution:
function precision(a) {
var e = 1;
while (Math.round(a * e) / e !== a) e *= 10;
return Math.log(e) / Math.LN10;
}
Edit: a more complete solution with edge cases covered:
function precision(a) {
if (!isFinite(a)) return 0;
var e = 1, p = 0;
while (Math.round(a * e) / e !== a) { e *= 10; p++; }
return p;
}
One possible solution (depends on the application):
var precision = (12.3456 + "").split(".")[1].length;
If by "precision" you mean "decimal places", then that's impossible because floats are binary. They don't have decimal places, and most values that have a small number of decimal places have recurring digits in binary, and when they're translated back to decimal that doesn't necessarily yield the original decimal number.
Any code that works with the "decimal places" of a float is liable to produce unexpected results on some numbers.
There is no native function to determine the number of decimals. What you can do is convert the number to string and then count the offset off the decimal delimiter .:
Number.prototype.getPrecision = function() {
var s = this + "",
d = s.indexOf('.') + 1;
return !d ? 0 : s.length - d;
};
(123).getPrecision() === 0;
(123.0).getPrecision() === 0;
(123.12345).getPrecision() === 5;
(1e3).getPrecision() === 0;
(1e-3).getPrecision() === 3;
But it's in the nature of floats to fool you. 1 may just as well be represented by 0.00000000989 or something. I'm not sure how well the above actually performs in real life applications.
Basing on #blackpla9ue comment and considering numbers exponential format:
function getPrecision (num) {
var numAsStr = num.toFixed(10); //number can be presented in exponential format, avoid it
numAsStr = numAsStr.replace(/0+$/g, '');
var precision = String(numAsStr).replace('.', '').length - num.toFixed().length;
return precision;
}
getPrecision(12.3456); //4
getPrecision(120.30003300000); //6, trailing zeros are truncated
getPrecision(15); //0
getPrecision(120.000)) //0
getPrecision(0.0000005); //7
getPrecision(-0.01)) //2
Try the following
function countDecimalPlaces(number) {
var str = "" + number;
var index = str.indexOf('.');
if (index >= 0) {
return str.length - index - 1;
} else {
return 0;
}
}
Based on #boolean_Type's method of handling exponents, but avoiding the regex:
function getPrecision (value) {
if (!isFinite(value)) { return 0; }
const [int, float = ''] = Number(value).toFixed(12).split('.');
let precision = float.length;
while (float[precision - 1] === '0' && precision >= 0) precision--;
return precision;
}
Here are a couple of examples, one that uses a library (BigNumber.js), and another that doesn't use a library. Assume you want to check that a given input number (inputNumber) has an amount of decimal places that is less than or equal to a maximum amount of decimal places (tokenDecimals).
With BigNumber.js
import BigNumber from 'bignumber.js'; // ES6
// const BigNumber = require('bignumber.js').default; // CommonJS
const tokenDecimals = 18;
const inputNumber = 0.000000000000000001;
// Convert to BigNumber
const inputNumberBn = new BigNumber(inputNumber);
// BigNumber.js API Docs: http://mikemcl.github.io/bignumber.js/#dp
console.log(`Invalid?: ${inputNumberBn.dp() > tokenDecimals}`);
Without BigNumber.js
function getPrecision(numberAsString) {
var n = numberAsString.toString().split('.');
return n.length > 1
? n[1].length
: 0;
}
const tokenDecimals = 18;
const inputNumber = 0.000000000000000001;
// Conversion of number to string returns scientific conversion
// So obtain the decimal places from the scientific notation value
const inputNumberDecimalPlaces = inputNumber.toString().split('-')[1];
// Use `toFixed` to convert the number to a string without it being
// in scientific notation and with the correct number decimal places
const inputNumberAsString = inputNumber.toFixed(inputNumberDecimalPlaces);
// Check if inputNumber is invalid due to having more decimal places
// than the permitted decimal places of the token
console.log(`Invalid?: ${getPrecision(inputNumberAsString) > tokenDecimals}`);
Assuming number is valid.
let number = 0.999;
let noOfPlaces = number.includes(".") //includes or contains
? number.toString().split(".").pop().length
: 0;
5622890.31 ops/s (91.58% slower):
function precision (n) {
return (n.toString().split('.')[1] || '').length
}
precision(1.0123456789)
33004904.53 ops/s (50.58% slower):
function precision (n) {
let e = 1
let p = 0
while(Math.round(n * e) / e !== n) {
e *= 10
p++
}
return p
}
precision(1.0123456789)
62610550.04 ops/s (6.25% slower):
function precision (n) {
let cur = n
let p = 0
while(!Number.isInteger(cur)) {
cur *= 10
p++
}
return p
}
precision(1.0123456789)
66786361.47 ops/s (fastest):
function precision (n) {
let cur = n
let p = 0
while(Math.floor(cur) !== cur) {
cur *= 10
p++
}
return p
}
precision(1.0123456789)
Here is a simple solution
First of all, if you pass a simple float value as 12.1234 then most of the below/above logics may work but if you pass a value as 12.12340, then it may exclude a count of 0. For e.g, if the value is 12.12340 then it may give you a result of 4 instead of 5. As per your problem statement, if you ask javascript to split and count your float value into 2 integers then it won't include trailing 0s of it.
Let's satisfy our requirement here with a trick ;)
In the below function you need to pass a value in string format and it will do your work
function getPrecision(value){
a = value.toString()
console.log('a ->',a)
b = a.split('.')
console.log('b->',b)
return b[1].length
getPrecision('12.12340') // Call a function
For an example, run the below logic
value = '12.12340'
a = value.toString()
b = a.split('.')
console.log('count of trailing decimals->',b[1].length)
That's it! It will give you the exact count for normal float values as well as the float values with trailing 0s!
Thank you!
This answer adds to Mourner's accepted solution by making the function more robust. As noted by many, floating point precision makes such a function unreliable. For example, precision(0.1+0.2) yields 17 rather than 1 (this might be computer specific, but for this example see https://jsfiddle.net/s0v17jby/5/).
IMHO, there are two ways around this: 1. either properly define a decimal type, using e.g. https://github.com/MikeMcl/decimal.js/, or 2. define an acceptable precision level which is both OK for your use case and not a problem for the js Number representation (8 bytes can safely represent a total of 16 digits AFAICT). For the latter workaround, one can write a more robust variant of the proposed function:
const MAX_DECIMAL_PRECISION = 9; /* must be <= 15 */
const maxDecimalPrecisionFloat = 10**MAX_DECIMAL_PRECISION;
function precisionRobust(a) {
if (!isFinite(a)) return 0;
var e = 1, p = 0;
while ( ++p<=MAX_DECIMAL_PRECISION && Math.round( ( Math.round(a * e) / e - a ) * maxDecimalPrecisionFloat ) !== 0) e *= 10;
return p-1;
}
In the above example, the maximum precision of 9 means this accepts up to 6 digits before the decimal point and 9 after (so this would work for numbers less than one million and with a maximum of 9 decimal points). If your use-case numbers are smaller then you can choose to make this precision even greater (but with a maximum of 15). It turns out that, for calculating precision, this function seems to do OK on larger numbers as well (though that would no longer be the case if we were, say, adding two rounded numbers within the precisionRobust function).
Finally, since we now know the maximum useable precision, we can further avoid infinite loops (which I have not been able to replicate but which still seem to cause problems for some).