Be careful with JS numbers
blog.greweb.fr
blog.greweb.fr
(Fortunately, if they're ID's where they need to stay exact, then you probably don't need to do any math on them! Although once a coworker of mine had to write a bitwise XOR function in JavaScript that operated on large ID numbers represented as strings. That was fun...)
My advice is to store those ID's with a leading "$" character or something similar. Removes the temptation to treat them like numbers.
-Peter Seibel Interview with Brendan Eich "who under intense time pressure, created JavaScript", Coders at Work, p.136
I've had the same problem (that platform wouldn't ha. It's… annoying (also bullshit: in the worst case — CPython <= 3.2 — basic arithmetic operations will take ~20µs on my machine aside from divisions which take a bit more and if that shows up in profiling use cdecimal, CPython 3.3 [integrated cdecimal] or pypy)
... apply that logic to their paycheck and let them deal with being underpaid by a bizarre amount because of rounding.
Or apply it to their investment accounts so the errors accumulate for a few decades.
Nothing like an object lesson to remedy bad behavior.
Then add a decimal point when you display.
If you are dealing with stocks or interest I suggest storing tenths, or hundreds of a cent to avoid rounding errors.
Which is enough for even the united states national budget, let alone more prosaic uses.
Of course, floating point imprecision results in more surprising behaviors than integer overflow on the whole, but the danger is still there no matter what language you use (not counting the languages with full numeric towers, like Scheme).
For example, the parseInt function mentioned in the article actually does magic base determination. Your string will be parsed into a base-10 number, unless it begins with '0x' in which case base-16 is used, or if it begins with a leading '0' then it is treated as base-8.
This last case has stung me on several occasions when parsing user input into numbers: User puts a leading-zero, and you magically end up with octal conversions. (I believe this whole octal thing has been deprecated in recent JS implementations).
In any case it's sensible to specify the 'radix' whenever using the parseInt function, as in parseInt(numberString, 10);
parseInt('12', 10); => 12
Number('12'); => 12
parseInt('12x', 10); => 12
Number('12x'); => NaNAll of a sudden, tweet ids got rounded off to point to completely different entries!
https://dev.twitter.com/docs/twitter-ids-json-and-snowflake
Other JSON parsers may also be affected.
So it can happen to anyone and it's a real issue for any JSON API.
I get a lot of flak on here for that opinion which is odd.
Since it has no types per se, it doesn't make much sense to think of an 'integer type'. Javascript only has a number primitive, which is a IEEE 754 float.
The issue I have with dynamic languages with types is that the type is usually inferred based on the operation. It's very easy to make mistakes and for those mistakes not to be apparent until the shit hits the fan.
Fully statically typed languages put these concerns right in your face and make you think about them.
That depends slightly - if your compiler uses Damas-Milner type inference, it's possible that the compiler will assign the most general type signature possible to your function, which will not prevent this type of error, as operations such as addition work on either integral or floating point numbers.
What you're really after is a strongly typed language that also has explicit type declarations (or a programmer that's reliable enough always to include them even when they are optional).
That's about as wrong as can be.
In fact, it's the exact opposite (type inference can only be a property of statically typed languages)
int i = 10;
int j = 20;
String s = "Test " + i + j;
In Python the equivalent is an error.The 'in your face' difference between a statically typed language and dynamic one is the time difference between the compilation error and an execution error. One tool for working effectively with dynamically typed languages is to keep that time difference short with tools like unit tests.
By this logic, no bignum library could exist because machine code doesn't have bignums, and everything gets compiled to machine code and/or run by an interpreter that's been compiled to machine code.
Turns out that 1000000 * 8.2 = 8199999.999999999
Sometimes we learn the hard way. The bug was getting written into an XML document and pushed to an embedded device over HTTP which was expecting an int and caused the device to crash. We fixed both bugs.
// Scheme
(print (* 1000000 8.2))
> 8199999.999999999
// Python
>>> 1000000 * 8.2
8199999.999999999
//PHP
> 1000000 * 8.2
> 8199999.999999999 # Ruby 1.8.7
1.8.7 :022 > 1000000 * 8.2
=> 8200000.0
# Ruby 1.9.2
1.9.2p320 :001 > 1000000 * 8.2
=> 8199999.999999999 printf("%lf\n", 1000000 * 8.2);
8200000.000000
Here, printf() is doing the necessary rounding to hide the fact that 8.2 isn't exactly representable. It's interesting that other languages don't do something similar when outputting a float to text. //Python
>>> repr(1000000 * 8.2)
'8199999.999999999'
>>> "%lf" % (1000000 * 8.2)
'8200000.000000' $ uname -p
x86_64
$ php -v
PHP 5.4.6-1ubuntu1 (cli) (built: Aug 22 2012 21:13:52)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
$ php -r 'var_dump(1000000 * 8.2);'
float(8200000)
$2. An event counter is not going to reach 2^50.
I have determined by experience that 9007199254740995
(which is 2^53+3) is the smallest not representable
integer in Javascript.
Here's something to drop in your browser console as an amusing illustration of this 9007199254740994 ===
(9007199254740995 - 1)
and 9007199254740995 ===
(9007199254740995 - 1) 9007199254740995 - 1 - 1 - 1 - 1https://developers.google.com/web-toolkit/doc/latest/DevGuid...
The Number type has exactly 18437736874454810627 (that is, 264-253 +3) values, representing the double-precision 64-bit format IEEE 754 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic, except that the 9007199254740990 (that is, 253-2) distinct "Not-a-Number" values of the IEEE Standard are represented in ECMAScript as a single special NaN value.
Actually, JS has integer typed arrays.
new Uint8Array([1,100,300])
[1, 100, 44]
new Uint16Array([-1,2,300])
[65535, 2, 300]
new Uint32Array([-1,2,300])
[4294967295, 2, 300]
Here's the spec: