0

Will Math.pow return the same result (for the same input) on all Node.js platforms?

I guess that JavaScript arithmetic results are always the same (i.e. deterministic albeit inexact) because that's defined by the IEEE 754.

Conversely I guess that the Math function results aren't, necessarily -- especially e.g. pow where (in theory) different platforms might have different cost/accuracy trade-off in the implementation.

What if I restrict the question though to "all Math.pow results on Node.js" -- e.g. is the Math library sufficiently similar on all Node.js platform implementations?

ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • The floating point arithmetic is pretty much the same across all cpus and systems (it is standarized after all). What is not the same is the conversion from/to floats (and probably every code depends on it at some point, e.g. you use constants, you print results, etc.). It is irrelevant whether this is in Node.js or not. If you need exact same arithmetic then do not depend on it. You may be forced to use some other solution (e.g. decimals). – freakish Dec 14 '18 at 15:38
  • Also read this: https://gafferongames.com/post/floating_point_determinism/ Although the article is about C/C++ in the context of games, many issues apply to any JavaScript engine as well (which at the bottom is just a program written in C/C++). The problem is far from trivial. – freakish Dec 14 '18 at 15:44
  • @freakish Given that the hardware level is always compatible, I wondered if all Node.js instances/implementations.platforms might use the same `Math` library implementation and thus produce identical results too -- e.g. if I call `Math.pow` using any input parameters, round the result to 6 or 8 significant digits, and present that as a string, would that give the same result on every platform? – ChrisW Dec 14 '18 at 15:59
  • Combining my long comment into a short answer: no. :) There is no such guarantee and in fact it is known not to work as expected. Cross platform floating point arithmetic is a pain in the a**. – freakish Dec 14 '18 at 16:00
  • Dang. Oh well ... you said "decimal" so perhaps you were suggesting https://github.com/MikeMcl/decimal.js/ – ChrisW Dec 14 '18 at 16:03
  • yes, that's the library I've used before. It is a bit painful to work with (you don't have symbolical plus `+`, minus `-`, etc) but it does the job. Also note that it performs horribly bad compared to floating point arithmetic (which is not surprising). Use it if you don't actually do millions of calculations. – freakish Dec 14 '18 at 16:05
  • I haven't noticed that that JS supports arithmetic operator overloading (so, I couldn't complain about having to use methods like `plus`). Thank you! – ChrisW Dec 14 '18 at 16:08
  • 1
    Yeah, it doesn't. Yet another reason to rant on JS. :D Good luck! I'll gather my comments into an answer later. – freakish Dec 14 '18 at 16:10
  • If you wanted to repost all that as an answer, then I could upvote it etc., and maybe accept. I'm slightly nervous FWIW that the-powers-that-be might delete your helpful comments. – ChrisW Dec 14 '18 at 16:11

1 Answers1

2

So I'm going to talk about floating point arithmetic in general. Since Pow is just a subset it applies to it as well.

Cross platform floating point arithmetic is unfortunately a pain. It is not deterministic even under the assumption that the implementation is the same. One of the issues is that while floating point arithmetic is standardized, the conversion from/to floats is not (and this happens at the very lowest level of NodeJS, I don't count it as a piece of NodeJS' implementation cause it comes from the standard C lib).

Heres a helpful article: https://gafferongames.com/post/floating_point_determinism/

It is possible to get deterministic results for floating calculations across multiple computers provided you use an executable built with the same compiler, run on machines with the same architecture, and perform some platform-specific tricks.

It is incredibly naive to write arbitrary floating point code in C or C++ and expect it to give exactly the same result across different compilers or architectures, or even the same results across debug and release builds.

In your case the application that the text refers to is the NodeJS binary itself. Note that the same version of NodeJS is weaker then the same binary. It's not enough.

So if you have the same binary across the same machines and the code itself is deterministic (how would you know that? NodeJS does lots of stuff under the hood) then your floating point arithmetic has a very good chance to be deterministic as well. But can you guarantee this? Now and in the future? Isn't this hard?

The alternative would be to use some decimal library (e.g. https://github.com/MikeMcl/decimal.js/ ). Note that it sacrifices performance for correctness. I advise going down that road if performance is not absolutely critical (and it shouldn't be, you use JS after all).

Community
  • 1
  • 1
freakish
  • 54,167
  • 9
  • 132
  • 169
  • Thank you -- for the explanation of the problem and the link to a possible solution -- the comments, the references collected in that article, helped explain why (or under what conditions) it's not deterministic. – ChrisW Dec 15 '18 at 05:26