Different results of Math.hypot() on Chrome and Firefox - javascript

When I run the simple calculation below the results on Chrome and Firefox slightly differ.
Chrome: 56.1124478168614
Firefox: 56.11244781686139
let x = -24.42;
let y = -50.519999999999925;
console.log(Math.hypot(x, y));
Is there a hole in the specification of Math.hypot() or is one of the browsers implementing it in a wrong way?
Edit: In Firefox Math.hypot(x, y) gives the same result as Math.sqrt(x*x, y*y), in Chrome the result from Math.hypot(x, y) is slightly different. Therefore I suspect Firefox is doing the calculation correctly.

Although Math.js is the same code in both browsers, different engines have different algorithms for performing basic arithmetic. For example, there are many different methods of computing a square root, and it is unlikely that two different engines would share the exact same implementation.
There are efforts to standardise precision across engines, yet they are as of yet unsuccessful. See this article for example.
As to why Math.hypot in Chrome would return a different value to doing the calculation manually in the same engine, Math.hypot is intended as an efficient approximation - not just a neat way of wrapping up the work into a single function. Thus, depending on the implementation, its results may differ from the actual calculation. You are right in stating that in this case, Firefox has the more numerically accurate implementation, as evidenced by your simple test.

In Firefox Math.hypot(x, y) gives the same result as Math.sqrt(x*x, y*y)
That lets us make a fairly confident guess for how Firefox implemented Math.hypot :-)
in Chrome the result from Math.hypot(x, y) is slightly different
Here is Chrome's implementation:
https://chromium.googlesource.com/v8/v8/+/master/src/builtins/math.tq#389
As you can see from the comment in line 421, a Kahan summation is used to avoid/minimize rounding errors -- so apparently the intention was to be more accurate than a simple sqrt(x*x + y*y) implementation. (I've tried to verify whether that's actually the outcome in this case, but Wolfram Alpha just rounds to 56.1124, and I don't know of another convenient infinite-precision floating-point evaluator out there, so I can't say for sure.)
doing the calculation correctly
In the presence of limited precision and rounding errors, the "correct" way is hard to define. For example, there are situations where the (mathematically equivalent!) expressions (a * b) / c and a * (b / c) produce different results due to rounding, and what's more, where the values of a, b, c determine which way of computing the result gets closer to the (unlimited-precision) theoretical result, so each implementation could get "lucky" or "unlucky".

Related

Are browser differences in the last digit of a JavaScript Math function (atan2) within spec?

I'm seeing differences between Firefox and Safari in the last digit of the output from Math#atan2.
My code:
Math.atan2(-0.49999999999999994, 0.8660254037844387)
Safari (12.1.1) gives -0.5235987755982988 but Firefox (Mac/67.0) gives -0.5235987755982987.
This is of course a tiny difference. However, it seems that all implementations should yield the same output across all inputs. A difference like this could, for example, cause an if statement to follow different paths depending on browser.
Does what I'm seeing violate any version of the ECMAScript spec?
The ECMAScript 2015 spec has this to say:
The behaviour of the functions acos, acosh, asin, asinh, atan, atanh, atan2, cbrt, cos, cosh, exp, expm1, hypot, log,log1p, log2, log10, pow, random, sin, sinh, sqrt, tan, and tanh is not precisely specified here except to require specific results for certain argument values that represent boundary cases of interest. For other argument values, these functions are intended to compute approximations to the results of familiar mathematical functions, but some latitude is allowed in the choice of approximation algorithms.The general intent is that an implementer should be able to use the same mathematical library for ECMAScript on a given hardware platform that is available to C programmers on that platform.
Although the choice of algorithms is left to the implementation, it is recommended (but not specified by this standard) that implementations use the approximation algorithms for IEEE 754-2008 arithmetic contained in fdlibm, the freely distributable mathematical library from Sun Microsystems (http://www.netlib.org/fdlibm).
The 5.1 spec has similar language.
So I think it's safe to say this behavior doesn't violate the spec.
Floating point differences like that will happen on different CPUs/FPUs and different math libraries across any language or platform. If you depend on that level of precision being exactly right, you'd be in trouble. You should always treat floating point values as "fuzzy".
ECMA spec does not specify the precision:
The Math.atan2() function returns the angle in the plane (in radians)
between the positive x-axis and the ray from (0,0) to the point (x,y),
for Math.atan2(y,x).
must be some floating pt thing. I suggest adding some threshold check instead of using equals on the conditions.

Options to speed up Math.pow() in JavaScript?

I have some code which requires many Math.pow() function calls per second. In testing it seems to be a very large bottleneck to the performance of the code.
The results don't need to be precise - an accuracy of anywhere upwards of 85% should done fine - but my question would be is there any way I can somehow speed these calculations up? Maybe at the cost of some precision?
Edit: these calculations are very unlikely to repeat so a cache wouldn't work.
at the cost of some precision
How much loss of precision? If you only need correct answers by a factor of 2, you could use bitwise manipulation.
function pow2(n) {
return 2 << (n-1);
}
console.log(pow2(n) === Math.pow(2, n));
The Number constructor (including number literals) use only floating point numbers. This function converts the floats to 32-bit integers as described here.
Otherwise, I doubt you'll be able to beat the optimized native implementation of Math.pow.
jsPerf is a great tool for trying multiple techniques to find the fastest one.
This could vary quite a bit by browser or operating system, but so far it turns out that Math.pow is much faster in my environment (Chrome 42, 64-bit Linux) until you open up dev tools. With dev tools open, it's slightly faster to multiply the number as many times as you need depending on the power, as in the following example:
function pow(num, pow) {
var result = num;
while (--pow) {
result *= num;
}
return result;
}
I'm running out of different ideas, but you can see what I have so far here:
http://jsperf.com/math-pow-alternatives
There is also a lot of overhead just to calling a function (hundreds of thousands of times). In this case it seems like Math.pow is the way to go, but there might be other ways to improve performance (or at least perceptible performance). If the code is blocking and the browser is experiencing some lag, you might try using web workers, or limiting the number of calculations per frame. You could also try to reduce the amount of function calls, or make sure you're interacting very minimally with the DOM (especially during the calculations, but preferably not at all).
Without a more concise code sample it will be difficult to fine-tune your code's performance.

In Javascript, which operator is faster, the '*' multiply or '/' divide?

In javascript, is there a speed advantage between the multiplication operator and the division operator? As an example...
var foo = bar * 0.01;
var foo = bar / 100;
foo is the same for both, but which statement returns the value of foo the fastest? I know this may be an incredibly small difference, however, when loop processing large amounts of data it could make a bigger difference than realized, which would then make a difference in how I construct equations to facilitate the processing.
I would say, it depends on the implementation. I would just make an own test somehow or try to google it.
For most machines, multiplications is faster, but the raw CPU speed is not decisive when it comes to scripting languages. Even when the implementation is the same, the execution time for one or the other will not differ so much, since the overhead of scripting languages is normally much bigger.
Normally the difference between different operations is so small, that it is not worth it to think about it. When you must, you probably are using the wrong language, anyhow.
In computer systems, the only basic operators are + (adders) and (*) multipliers. You either add (negative or positive) numbers or rotate numbers (either left or right for multiplication and division respectively). You should be able to work it out whether multiplication or division takes longer...
*btw...unless I am wrong, your question has nothing to do with javascript. Javascript is an interpreted language with engines such as spidermonkey or rhino....
FYI You should read this - directly from the main people....to have better insight of "what" might be happening.

What's the fastest way to square a number in JavaScript?

What's the fastest way to square a number in JavaScript?
function squareIt(number) {
return Math.pow(number,2);
}
function squareIt(number) {
return number * number;
}
Or some other method that I don't know about. I'm not looking for a golfed answer, but the answer that's likely to be shortest in the compiler, on the average.
Edit: I saw Why is squaring a number faster than multiplying two random numbers? which seemed to indicate that squaring is faster than multiplying two random numbers, and presumed that n*n wouldn't take advantage of this but that Math.pow(n,2) would. As jfriend00 pointed out in the comments, and then later in an answer, http://jsperf.com/math-pow-vs-simple-multiplication/10 seems to suggest that straight multiplication is faster in everything but Firefox (where both ways are similarly fast).
Note: Questions like this change over time as browser engines change how their optimizations work. For a recent look comparing:
Math.pow(x1, 2)
x1 * x1
x1 ** 2 // ES6 syntax
See this revised performance test and run it in the browsers you care about: https://jsperf.com/math-pow-vs-simple-multiplication/32.
As of April 2020, Chrome, Edge and Firefox show less than 1% difference between all three of the above methods.
If the jsperf link is not working (it seems to be occasionally down), then you can try this perf.link test case.
Original Answer from 2014:
All performance questions should be answered by measurement because specifics of the browser implementation and the particular scenario you care about are often what determine the outcome (thus a theoretical discussion is not always right).
In this case, performance varies greatly by browser implementation. Here are are results from a number of different browsers in this jsperf test: http://jsperf.com/math-pow-vs-simple-multiplication/10 which compares:
Math.pow(x1, 2)
x1 * x1
Longer bars are faster (greater ops/sec). You can see that Firefox optimizes both operations to be pretty much the same. In other browsers, the multiplication is significantly faster. IE is both the slowest and shows the greatest percentage difference between the two methods. Firefox is the fastest and shows the least difference between the two.
In ES6 you can do the following with Exponentiation (x ** y), which produces the same result as Math.pow(x,y):
function squareIt(number) {
return number ** 2;
}
console.log(squareIt(5));
or you can use a JavaScript library called BigInteger.js for the purpose.
alert(bigInt(5).square());
<script src="https://cdnjs.cloudflare.com/ajax/libs/big-integer/1.6.40/BigInteger.min.js"></script>
In general, x * x is either much faster than or about the same as a pow() call in any language. pow() is a general exponential designed to work with floating point arguments, and it usually uses a calculation that has a lot more operations than a single multiplication. It's notoriously slow. Some pow() implementations will helpfully filter out integer powers for special evaluations, like for x^4 it might do x2=x * x, x4=x2 * x2, but adding special conditions like that can slow down the general implementation, and the x * x vs. pow() rule is so well known among programmers you can't really count on the library implementation to help you out. This is standard advice in numerical analysis: never use pow() for x^2 (or x^.5). At best, it's no slower than the pow implementation, if it's optimized out as x * x at compile time, and at worst, it's horribly slower (and probably not as accurate either). You could go and test it on every possible platform you expect your code to run on, but in real life, there's no good reason to use pow() for squares. There can be good reasons to write a convenience function that does x * x, but if the language allows it, it's a good idea to make sure that it's marked up so that there's no actual function call going on at the machine level. Unfortunately, I don't think Javascript has anything like that, but I suspect that the JIT compilers are usually smart enough to render short functions like that without a jump.
Regarding the issue of x * x vs. x * y, the former would often be faster simply because it avoids a MOV at the machine level (aside from the considerations in the post you referenced), but it's pretty certain that the JS engine is smart enough not to do an extra MOV if the operand is already in a register. It's not going to load x from memory and then load it from memory again, or move it from one register into another. That's a basic behavior of optimizing compilers. You have to keep in mind that the compiler is going to do a lot of rearranging and consolidation of algebraic operations, so when you write x * x, a lot of things could be going on depending on what happened to x previously or happens to it later. This is another reason to avoid pow(), since the optimizer can do a lot of tricks with x * x that may not be available if it does a pow() call instead. Again, you can hope that it intelligently inlines pow(x,2) to x * x, but don't count on it.

What is the most efficient way to handle points / small vectors in JavaScript?

Currently I'm creating an web based (= JavaScript) application thata is using a lot of "points" (= small, fixed size vectors). There are basically two obvious ways of representing them:
var pointA = [ xValue, yValue ];
and
var pointB = { x: xValue, y: yValue };
So translating my point a bit would look like:
var pointAtrans = [ pointA[0] + 3, pointA[1] + 4 ];
var pointBtrans = { x: pointB.x + 3, pointB.y + 4 };
Both are easy to handle from a programmer point of view (the object variant is a bit more readable, especially as I'm mostly dealing with 2D data, seldom with 3D and hardly with 4D - but never more. It'll allways fit into x,y,z and w)
But my question is now:
What is the most efficient way from the language perspective - theoretically and in real implementations?
What are the memory requirements?
What are the setup costs of an array vs. an object?
...
My target browsers are FireFox and the Webkit based ones (Chromium, Safari), but it wouldn't hurt to have a great (= fast) experience under IE and Opera as well...
Arrays are faster to create, but if you consider access time it's the other way around. Also note, that constructor form is fast to create and access. It has the best of both words in modern implementations new Vector(x, y) - [Test]
Browsers tested: Chrome 10, Firefox 3.6, Firefox Beta 4.0b9, IE 9 Preview 7, Opera 11
My hunch is that Arrays will give you better performance.(!)
That said, the code is already significantly less readable in your Array example than in your Object example. The gains are likely slight, so I suggest you do some basic benchmarking and back-of-the-napkin math to put a real number on the tradeoff.
For starters, you could
Start a timer
Construct 1 thousand random [X,Y] Arrays
Access their fields 1 million times.
Repeat with Objects and compare.
(!) - A good example of why benchmarking is so useful: Arrays are indeed better for creation, but Objects are better for access, which could be very important (depending on your needs). galambalazs has written a great test for this case: http://jsperf.com/object-vs-array
Thanks for all the answers and the input. Very interesting were the results of the test written by galamalazs: http://jsperf.com/object-vs-array/2
Taking all aspects together we'll get:
Arrays should be indexed by number and not by string (arr[0] vs. arr['0'])
Performance between the Object and the Array form differs mostly by implementation not by type.
There is no winner, it changes from implementation to implementation
Future implementations of the browsers known today might also change who's winning - in either way
On Chromium the Arrays will use half the memory of the Object - but we are talking about 40 MB and 80 MB for one million instances - that is 40 to 80 bytes each.
The memory consumption of other JavaScript implementations is not known - but it'll most probably also differ as much as the performance.
So in the end both options are sensible and only the code readability will make the decision!
If it's mostly for storing data with trivial work (like in my current project) the Object way is the way to go. An mouse.x and mouse.y trivially shows the developer intend.
In mostly mathematically oriented applications with vector maths like coordinate transformations (especially going to 3D) the best way would be the Array case as things like matrix multiplications would look more native to the developer and show his intent.

Categories

Resources