Hacker News new | ask | show | jobs
by gloob 5180 days ago
This sort of thing is an intrinsic property of floating point math. It has limited precision. When the numbers get sufficiently large, that precision is insufficient to distinguish successive integers. That is to say, this is symptomatic of PHP implementing floating point stuff correctly.

This is what ghci (Haskell) says:

  Prelude> 9223372036844775807 == 9223372036844775808
  False
  Prelude> 9223372036844775807.0 == 9223372036844775808.0
  True
This is what Python says:

  >>> 9223372036844775807 == 9223372036844775808
  False
  >>> 9223372036844775807.0 == 9223372036844775808.0
  True
Here is what SBCL (Common Lisp) says:

  * (= 9223372036844775807 9223372036844775808)
  NIL
  * (= 9223372036844775807.0 9223372036844775808.0)
  T
Lua:

  > print(9223372036844775807 == 9223372036844775808)
  true (!!!!!)
  > print(9223372036844775807.0 == 9223372036844775808.0)
  true
Javascript:

  alert(9223372036844775807 == 9223372036844775808)
  true (!!!!!)
  alert(9223372036844775807.0 == 9223372036844775808.0)
  true
Other languages that will also do this[1]: Javascript, Lua. Languages that won't: anything with actual, honest-to-god integers, and not floats or doubles masquerading as them.[2] Languages that actually handle numbers sensibly: Lisp.[3] I'm not familiar with any others that actually treat rational numbers like rational numbers, but I expect there are some. (It's still, of course, impossible to treat real numbers like real numbers, meaning that this sort of thing will also happen there.)

[1] Well, not the string-to-number bit, but whatever.

[2] Except for the niggle that they'll still do this when you're using floating point numbers, because this is what floating point numbers do.

[3] https://en.wikipedia.org/wiki/Numerical_tower

2 comments

I think you may be missing the point, or maybe it's I who am missing the point. Your three very thorough examples are a good way of showing how (most?) languages handle floating-point arithmetic vs. arbitrary arithmetic.

But it seems to me - and let me stress that I am not a PHP developer and won't be bothered to install PHP on my machine at this time - that PHP is failing to exhibit exactly the behavior your code examples are giving.

Put it another way - type coercion 'run amok' being another thing entirely, you are correct that this bug stems from the fact that PHP is converting these integers to floating-point, and the standard floating point implementations will all behave in this exact way (thus, not a PHP bug.)

However, the issue here is that (again, "most?") languages also provide an easy way to get to arbitrary-precision arithmetic - and indeed, in the three examples you posted, you simply encode in the most natural way (by simply writing them) the two integers and they automatically compare correctly.

My understanding is that this is not the case in PHP, and that is a shame.

I agree that, when we are talking about high-level languages, I prefer ones that will transparently convert integers to bignum when required. I'm just replying to the contention that (paraphrased) "this is a bug in PHP's handling of floating point numbers".
Ah, point taken, sorry about that. :)
Lua internally represents any kind of number as a floating-point one.

http://www.lua.org/pil/2.3.html