How can I convert a long integer (as a string) to a numerical format in Javascript without javascript rounding it?
var ThisInt = '9223372036854775808'
alert(ThisInt+'\r' +parseFloat(ThisInt).toString()+'\r' +parseInt(ThisInt).toString());
I need to perform an addition on it before casting it back as a string & would prefer not to have to slice it two if at all possible.
All Numbers in Javascript are 64 bit "double" precision IEE754 floating point.
The largest positive whole number that can therefore be accurately represented is 2^53 - 1. The remaining bits are reserved for the exponent.
Your number is exactly 1024 times larger than that, so loses 3 decimal digits of precision. It simply cannot be represented any more accurately.
In ES6 one can use Number.isSafeInteger( # ) to test a number to see if its within the safe range:
var ThisInt = '9223372036854775808';
console.log( Number.isSafeInteger( parseInt( ThisInt ) ) );
There is also a BigInteger library available which should be able to help, though, and avoid you having to do all the string and bit twiddling yourself.
EDIT 2018/12 there's now a native BigInt class (and new literal syntax) landed in Chrome and NodeJS.
With a little help from recursion, you can directly increment your decimal string, be it representing a 64 bit number or more...
/**
* Increment a decimal by 1
*
* #param {String} n The decimal string
* #return The incremented value
*/
function increment(n) {
var lastChar = parseInt(n.charAt(n.length - 1)),
firstPart = n.substr(0, n.length - 1);
return lastChar < 9
? firstPart + (lastChar + 1)
: firstPart
? increment(firstPart) + "0"
: "10";
}
You cannot do this with standard Javascript. But as always, there is a nifty little library to help us out, in this case BigInt.js, which will let you use arbitrary-precision integers.
Have you tried using the Number class?
var num = new Number(parseFloat(ThisInt))
Just use Number(ThisInt) for this instead of Int or float
Related
I have a string and I need to convert this string into another number system.
1959113774617397110401052 - in Decimal notation to thirty-tensary number system (10 to 36).
If i try to use this code:
var master = 1959113774617397110401052;
parseInt(master, 10).toString(36);
//8v0wc05bcz000000
It doesn't work properly.
Can you help me to know, where is my mistake and how to use this correctly.
Thank you!
The maximum integer JavaScript can safely handle is 9007199254740991. This is what we get if we call Number.MAX_SAFE_INTEGER. Your number, on the other hand, is significantly larger than this:
9007199254740991
1959113774617397110401052
Because of this, JavaScript isn't able to safely perform mathematical calculations with this number and there's no guarantee that you'll get an accurate result.
The MAX_SAFE_INTEGER constant 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 numbers between -(253 - 1) and 253 - 1.
Safe in this context refers to the ability to represent integers exactly and to correctly compare them. For example, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 will evaluate to true, which is mathematically incorrect. See Number.isSafeInteger() for more information.
— MDN's notes on Number.MAX_SAFE_INTEGER
You would need to use a multi-precision library like Decimal.js for integer calculations that exceed the range of signed Int32 resp. the continuous integer range representable by 64bit floats. As example:
var astr = '1959113774617397110401052'
var a =new Decimal(astr)
var out = '';
while( a > 0 ) {
var d = a.mod(36).toNumber();
a = a.divToInt(36);
if(d>9) d=d+39; // d+7 for upper case
out = String.fromCharCode(48+d)+out
}
var my_div = document.getElementById("my_div")
my_div.innerHTML += astr+" in base 36 is "+out;
<script src="https://raw.githubusercontent.com/MikeMcl/decimal.js/master/decimal.min.js"></script>
<div id="my_div"></div>
I was just going through the source code of particles.js and came across the following line of code:
this.speed.x = +((-options.maxSpeedX / 2) +
(Math.random() * options.maxSpeedX)).toFixed(2);
That line of code can be found HERE too.
Now the + sign right at the beginning of the expression has no difference in the equation. E.g.
(-2 + 5) = 3
Now...
+(-2 + 5) = 3
Another example:
(-5 + 2) = -3
Now..
+(-5 + 2) = -3
Why the plus sign at the beginning of the expression when it makes no difference to the outcome of the equation?
Your code is basically
x = +someNumber.toFixed(2);
Which is
x = +(someNumber.toFixed(2));
because the function call has a higher precedence than the + operator.
This makes
x = +(someNumberFormattedAsARoundedString);
Applying the unary plus operator converts the string back to a number. The net result is the rounding of the initial someNumber.
In this specific case you linked to, this looks like bad practice due to ignorance of what is a IEEE754 floating point number. It looks like the author tried to get fixed precision numbers, thus confusing the number storage and their representation (i.e. formatting).
.toFixed() returns a String. You need to cast it to Number. The unary plus + operator is used to convert/cast the string to number.
Returns
A string representation of numObj that does not use exponential notation and has exactly digits digits after the decimal place. The number is rounded if necessary, and the fractional part is padded with zeros if necessary so that it has the specified length. If numObj is greater than 1e+21, this method simply calls Number.prototype.toString() and returns a string in exponential notation.
It is not required in the cases when the result is already a number. Example, +(-2 + 5).
However, in below operation it is required.
this.speed.x = +((-options.maxSpeedX / 2) +
(Math.random() * options.maxSpeedX)).toFixed(2);
I need to do the following in JavaScript and so far been unable to find solutions to do it seamlessly:
Grab two integers in a specific order and pack them like Python's struct module.
This packed value, (bonus for supporting different endianness than host) will be turned into a 64 bit float (double). They must be arbitrary thus I might get an exponent representation of the integer (say, they could be 0xdeadbeef and 500):
In exp form:
1.0883076389305e-311
1.0883076389305000 * 10 ^ - 311
I need to convert it to the arbitrary precision, non-exponent form, so:
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000108830763893050000000000000000000000000000000000000000000000000000000000000000000000000000
That number converted to a string :)
I haven't found a way to do this in Javascript and I have to output some numbers like that which must support arbitrary precision, or at least, of a scale up to the 1024 exponent (or, say 400) of doubles.
Thanks!!
Note: I do need the "packing/unpacking' to be a faithful representation of those two numbers converted to a double/64bit float. But I don't care about, say, exporting to a string or raw buffer. As long as I get an arbitrary precision double representation for the double it's all fine.
1: Khronos has a specification in progress for a DataView interface as part of the WebGL TypedArray requirements, which combined with Int32Array and Float64Array would let you write your two ints into a buffer, and read them back out as a double.
Unfortunately browser support for this isn't common yet - to test your browser visit http://html5test.com/ and look at the section entitled "Native binary data".
Without the TypedArray support above I don't think there's any way to do this using bit-twiddling since Javascript's bit operators treat numbers as 32-bit unsigned values, so you'd have no access to the higher-order bits.
2: double variables don't have any specific form, IEE754 is just an internal representation.
3: that's the point at which you can attempt to show the actual precision. Unfortunately the built-in method, e.g. Number.toFixed(), doesn't support showinng more than 20 decimal places. You will need to parse the exponential form and manually construct a string with the appropriate number of leading zeros.
NB - the exponent range of a double is 2^1024, not 10^1024, hence the real limit is actually ~1.0E±308 - your example figure is smaller than that range.
EDIT actually, there might be a way, but I can't guarantee the precision of this:
take your two integers, call them hi and lo.
extract the exponent - exp = (hi >> 20) & 0x7ff
extract the sign - sign = (hi >> 31)
extract the mantissa - ((hi & 0xfffff) * Math.pow(2, 32) + lo) / Math.pow(2, 52)
result = (1 + m) * (Math.pow(2.0, exp - 1023))
if (sign) result *= -1
EDIT 2 - it works! See http://jsfiddle.net/alnitak/assXS/
var hex2double = function(input) {
var hi = parseInt(input.substring(0, 8), 16);
var lo = parseInt(input.substring(8 ), 16);
var p32 = 0x100000000;
var p52 = 0x10000000000000;
var exp = (hi >> 20) & 0x7ff;
var sign = (hi >> 31);
var m = 1 + ((hi & 0xfffff) * p32 + lo) / p52;
m = exp ? (m + 1) : (m * 2.0);
return (sign ? -1 : 1) * m * Math.pow(2, exp - 1023);
};
Enter a floating point number at http://babbage.cs.qc.edu/IEEE-754/Decimal.html, take the resulting hex string from the bottom row of output, and pass it to the function above. You should see an alert containing the original value.
EDIT 3 code fixed to account for the special case when the exponent bits are all zero.
I think you need a big number library for JavaScript such as http://jsfromhell.com/classes/bignumber.
I'm writing a function to extend a number with sign to a wider bit length. This is a very frequently used action in the PowerPC instruction set. This is what I have so far:
function exts(value, from, to) {
return (value | something_goes_here);
}
value is the integer input, from is the number of bits that the value is using, and to is the target bit length.
What is the most efficient way to create a number that has to - from bits set to 1, followed by from bits set to 0?
Ignoring the fact that JavaScript has no 0b number syntax, for example, if I called
exts(0b1010101010, 10, 14)
I would want the function to OR the value with 0b11110000000000, returning a sign-extended result of 0b11111010101010.
A number containing p one bits followed by q zero bits can be generated via
((1<<p)-1)<<q
thus in your case
((1<<(to-from))-1)<<from
or much shorter
(1<<to)-(1<<from)
if you have the number 2^q (= 1 shifted left by q) represented as an integer of width p + q bits, it has the representation:
0...010...0
p-1 q
then 2^q - 1 has the representation
0...01...1
p q
which is exactly the opposite of you want. So just flip the bits
hence what you want is NOT((1 LEFT SHIFT by q) - 1)
= ~((1 << q) - 1) in c notation
I am not overly familiar with binary mathematics in JavaScript... But if you need to OR a number with 0b11110000000000, then I assume you would just convert that to decimal (which would get you 15360), and do value | 15360.
Relevant info that you may find useful: parseInt("11110000000000", 2) converts a binary number (specified as a string) to a decimal number, and (15360).toString(2) converts a decimal number (15360 in this case) to a binary number (the result is a string).
Revised solution
There's probably a more elegant and mathematical method, but here's a quick-and-dirty solution:
var S = "";
for(var i=0;i<p;i++)
S += "1";
for(i=0;i<q;i++)
S += "0";
S = parseInt(S, 2); // convert to decimal
I am trying to perform something that is brain-dead simple in any other language but not javascript: get the bits out of float (and the other way around).
In C/C++ it would be something like
float a = 3.1415;
int b = *((int*)&a);
and vise-versa
int a = 1000;
float b = *((float*)&a);
In C# you can use the BitConverter
...floatBits or something alike in Java... Even in VB6 for Christ's sake you can memcpy a float32 into an int32. How on earth can I translate between and int and a float in javascript?
function DoubleToIEEE(f)
{
var buf = new ArrayBuffer(8);
(new Float64Array(buf))[0] = f;
return [ (new Uint32Array(buf))[0] ,(new Uint32Array(buf))[1] ];
}
You certainly don't get anything low-level like that in JavaScript. It would be extremely dangerous to allow recasting and pointer-frobbing in a language that has to be safe for untrusted potential-attacker web sites to use.
If you want to get a 32-bit IEEE754 representation of a single-precision value in a Number (which remember is not an int either; the only number type you get in JavaScript is double), you will have to make it yourself by fiddling the sign, exponent and mantissa bits together. There's example code here.
function FloatToIEEE(f)
{
var buf = new ArrayBuffer(4);
(new Float32Array(buf))[0] = f;
return (new Uint32Array(buf))[0];
}
Unfortunately, this doesn't work with doubles and in old browsers.
JavaScript uses double (IEEE 754) to represent all numbers
double consists of [sign, exponent(11bit), mantissa(52bit)] fields.
Value of number is computed using formula (-1)^sign * (1.mantissa) * 2^(exponent - 1023). (1.mantissa - means that we take bits of mantissa add 1 at the beginning and tread that value as number, e.g. if mantissa = 101 we get number 1.101 (bin) = 1 + 1/2 + 1/8 (dec) = 1.625 (dec).
We can get value of sign bit testing if number is greater than zero. There is a small issue with 0 here because double have +0 and -0 values, but we can distinguish these two by computing 1/value and checking if value is +Inf or -Inf.
Since 1 <= 1.mantissa < 2 we can get value of exponent using Math.log2 e.g. Math.floor(Math.log2(666.0)) = 9 so exponent is exponent - 1023 = 9 and exponent = 1032, which in binary is (1032).toString(2) = "10000001000"
After we get exponent we can scale number to zero exponent without changing mantissa, value = value / Math.pow(2, Math.floor(Math.log2(666.0))), now value represents number (-1)^sign * (1.mantissa). If we ignore sign and multiply that by 2^52 we get integer value that have same bits as 1.mantissa: ((666 / Math.pow(2, Math.floor(Math.log2(666)))) * Math.pow(2, 52)).toString(2) = "10100110100000000000000000000000000000000000000000000" (we must ignore leading 1).
After some string concat's you will get what you want
This is only proof of concept, we didn't discuss denormalized numbers or special values such as NaN - but I think it can be expanded to account for these cases too.
#bensiu answers is fine, but if find yourself using some old JS interpreter you can use this approach.
Like the other posters have said, JavaScript is loose typed, so there is no differentiation in data types from float to int or vice versa.
However, what you're looking for is
float to int:
Math.floor( 3.9 ); // result: 3 (truncate everything past .) or
Math.round( 3.9 ); // result: 4 (round to nearest whole number)
Depending on which you'd like. In C/C++ it would essentially be using Math.floor to convert to integer from float.
int to float:
var a = 10;
a.toFixed( 3 ); // result: 10.000