JavaScript misinterpretes number - javascript

I perform an AJAX call to generate an ID. This ID is sent back to the client in the response and shown in an input field. I was made aware that the ID displayed in the browser is not the one generated - the last digit differs. On the serverside I serialize data to pass it back to the client using Adobe ColdFusion's own serializeJSON() function. It recognizes the sequence of digits and serializes it as a number. I logged the contents of my variables on different places in my codde, it looked fine all the way. Only the browser does not do what I want/expect.
I boiled it down to this simple sample:
var stru = {"MYID":2761602017000540006};
console.dir(stru);
The console logs 2761602017000540000 instead of 2761602017000540006
Why is that? Is this number too large to be stored in JavaScript?

Is the number too large to be stored in JavaScript?
Yes, the max safe integer is 9,007,199,254,740,991 and the number you're attempting to send is 2,761,602,017,000,540,006 (which is a factor of ~1000x larger).
This is because the JavaScript number type follows the IEEE 754 64-bit floating point number format, which doesn't allow as for as large of numbers as a 64-bit integer normally would. You can see the definition of the number type value here in the ECMAScript spec 4.3.20.
I suggest you send the ID over as a String.

In JavaScript, one has at most 53 bits for integers. so you can not put integers larger that 53bits into javascript variables, so the other way is to use strings for saving this long id . I hope that this help you

As Arash said, your number is too long (more than 53 bits).
You can have more information on this topic: Javascript long integer
The only solution seems to be using string instead of numbers

Related

Why is parseInt() not converting my String of numbers correctly?

I have some logic within a function that takes a string of numbers called digits like so:
6145390195186705543
I then attempt to convert with parseInt() like so:
parseInt(digits)
The result of:
digits = parseInt(digits);
is
6145390195186705000
Can someone help me understand why this is the case? and how i can get an accurate conversion?
This is another version of "broken" floating point math: Javascript uses 64 bits to store numbers as small as the size of an atom up to the number of atoms in the universe. As that is quite a broad range it cannot be stored accurately, therefore the numbers are stored in an imprecise way but can represent a very broad range. In your case 6145390195186705000 is the inaccurate version JS is able to store as 6145390195186705543 cannot be stored.
and how i can get an accurate conversion?
You cannot store an "accurate number", therefore you cannot convert it accurately. However there are some libraries that allow you to work with strings as if they were numbers, such as BigIntJS.
As this is a common problem, this is going to be solved in the next JS version, see this proposal. You can currently test it in the new version of chrome.

Handling 64-bit numbers using AngularJS' $http.get()

In my Angular app I am making a $http.get() request to a URL that is responding with a json object. This object contains a value that is occasionally a very large number (e.g. 9106524608436223400). Looking at the network profiler in Chrome I can see that the number is coming down properly but when $http.get() has it's callback hit the number will be corrupted somewhat. I assume this is because the number is very large and not a string. Is there any way to get Angular to handle this response correctly or do I need to wrap my server's output as a string? Thanks.
Numbers in JavaScript are double precision floating point numbers. This means that they can only handle integer numbers with full precision up to 52 bits.
Any code for parsing the JSON that will represent the number as a regular number in JavaScript will be unable to give you the unchanged value.
The JSON standard doesn't specify any limitation for the range or precision for numbers. However, as JSON is based on a subset of the JavaScript syntax, one could argue that the format doesn't support numbers outside of what could be represented in JavaScript.
To safely get the value unchanged, you would need to put it as a string in the JSON, or split it up into two or more smaller numbers.

JavaScript numbers, all the same size in memory?

I'm reading the Number Type section of the book Professional JavaScript for Web Developers. It seems to say that all ECMAScript numbers are binary64 floating point, which is corroborated by this MDN article. But the book author also says:
Because storing floating-point values uses twice as much memory as storing integer values, ECMAScript always looks for ways to convert values into integers.
I expected numbers to each occupy the same amount of memory: 64 bits. And the MDN article says, "There is no specific type for integers". Anyone know what the book author meant? How can integers take up less memory when they're stored as 64-bit floats (if I have that right)? You'll find the whole section at the link above (free sample of the book).
JavaScript doesn't have any other number type than double precision floating point (except in ECMAScript 6 typed arrays), but the underlying implementation may choose to store the numbers in any way it likes as long as the JavaScript code behaves the same.
JavaScript is compiled nowadays, which means that it can be optimised in many ways that are not obvious in the language.
If a local variable in a function only ever takes on an integer value and isn't exposed outside the function in any way, then it could actually be implemented using an integer type when the code is compiled.
The implementation varies in different browsers. Currently it seems to make a huge difference in MS Edge, a big difference in Firefox, and no difference at all in Chrome: http://jsperf.com/int-vs-double-implementation (Note: jsperf thinks that MS Edge is Chrome 42.)
Further research:
The JS engines Spidermonkey (Firefox), V8 (Chrome, Opera), JavaScriptCore (Safari), Chakra (IE) and Rhino (and possibly others, but those are harder to find implementation details about) use different ways of using integer types or storing numbers as integers when possible. Some quotes:
"To have an efficient representation of numbers and JavaScript
objects, V8 represents both of us with a 32 bits value. It uses a bit
to know if it is an object (flag = 1) or an integer (flag = 0) called
here SMall Integer or SMI because of its 31 bits."
http://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/
"JavaScript does not have a built-in notion of an integer value, but
for efficiency JavaScriptCore will represent most integers as int32
rather than as double."
http://trac.webkit.org/wiki/JavaScriptCore
"[...] non-double values are a 32-bit type tag and a 32-bit payload,
which is normally either a pointer or a signed 32-bit integer."
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals
"In Windows 10 and Microsoft Edge, we’ve started optimizing Chakra’s
parser and the JIT compiler to identify non const variable
declarations of integers that are defined globally and are never
changed during the course of the execution time of the program."
https://blogs.windows.com/msedgedev/2015/05/20/delivering-fast-javascript-performance-in-microsoft-edge/
Because storing floating-point values uses twice as much memory as storing integer values, ECMAScript always looks for ways to convert values into integers.
This paragraph is complete nonsense. Ignore it!
Numbers are numbers. ECMAScript makes no distinction whatsoever between floating-point and integer numeric values.
Even within most JS runtimes, all numeric values are stored as double-precision floating point.
Not sure I fully understood your question, but "There is no specific type for integers" means that JavaScript doesn't recognize separate types for integers and floats, but they are both typed as Numbers. The int/float separation happens "behind the curtains", and that's what they meant by "ECMAScript always looks for ways to convert values into integers".
The bottom line is that you don't have to worry about it, unless you specifically need your variables to mimic integers or floats for use in other languages, in which case it's probably (did I say probably?) the best to pass them as strings (because you'd have trouble passing, say, 5.0 as a float because JS would immediatelly convert it to 5, exactly because of the "ECMAScript always looks for ways to convert values into integers" part).
alert(5.0); // don't expect a float from this

How do you store a googol in the database (and other very large numbers)?

How do you efficiently store very large and very small numbers from say 10^-100 to 10^100, so that you can use them to calculate values in a programming language like JavaScript.
JavaScript stores 10^100 as 1e+101, is there a way to do that in the database? The numbers would not often be that large, but I would like to do calculations with data such as 10^-34 * 2^16 or whatever, so the database should (I think) be storing these as numbers...
How does this work? How do you store numbers of this scale such that you can run computations with them?
By "the database", I'm thinking in general. I am messing around with MongoDB and Neo4j currently.
Databases themselves don't support numbers of arbitrary size in a native numeric format. Your general upper limit on numeric types is usually 8 bytes, which isn't anywhere near a googol.
You'll have to store the number either as a string (least efficient, easiest to work with, can be as precise as needed), as a byte array of arbitrary length (more efficient, harder to work with, still arbitrary precision), or in scientific notation (most efficient, harder to work with, and limited precision).
The first two, unfortunately, do eliminate the possibility of doing any server-side computation, since there wouldn't be a native numeric type that could support the range of valid values. All of the computation would have to be done client-side using a suitable numeric type.
If I were you, I'd separate the numerical value from the exponent. I personally don't have experience with MongoDB or Neo4j, but in MySQL (I'm sure they have similar terms) I'd create a table with an VARCHAR (text) column with whatever precision you'd like in your program (or how many unique numbers), and another VARCHAR column with length 3 (for max exponent 999). You can tinker with the values as you see fit, but that's all I can think of. If you want more flexible size values, I'd store the numbers on the server's file system using PHP rather than use databases.
You could use the double type.
The MySQL DOUBLE[(M,D)]
A normal-size (double-precision) floating-point number. Permissible
values are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0,
and 2.2250738585072014E-308 to 1.7976931348623157E+308. These are the
theoretical limits, based on the IEEE standard. The actual range might
be slightly smaller depending on your hardware or operating system.

JSON.Stringify() on big numbers alters the numeric value?

I have a WCF service operation that returns an object with long and List<string> properties. When I test the operation in a WCF application, everything works fine and the values are correct. However, I need to be able to call the service using jQuery and JSON format. The value of the long property apparently changes when I read it back in the OnSucceed function.
After searching I've found that JSON.stringify changes big values. So in code like this:
alert(JSON.stringify(25001509088465005));
...it will show the value as 25001509088465004.
What is happening?
Demo here: http://jsfiddle.net/naveen/tPKw7/
JavaScript represents numbers using IEEE-754 double-precision (64 bit) format. As I understand it this gives you 53 bits precision, or fifteen to sixteen decimal digits. Your number has more digits than JavaScript can cope with, so you end up with an approximation.
Do you need to do maths operations on this big number? Because if its just some kind of ID you can return it as a string and avoid the problem.

Categories

Resources