I don't understand, why I get some very strange values from trigonometric functions in JavaScript. For example:
Math.sin(Math.PI); // returns 1.2246467991473532e-16, but should return 0
Math.cos(Math.PI/2); // returns 6.123233995736766e-17, but should return 0
Math.sin(3.14); // returns 0.0015926529164868282, whitch is ok but
Math.sin(3.141592); // returns 6.535897930762419e-7!
I tried this in Mozilla and Chrome and got the same result. It seems the parameter of the trigonometric function is too precise.
Please help!
You could use Number.EPSILON
The Number.EPSILON property represents the difference between 1 and the smallest floating point number greater than 1.
and take the absolute delta of the value and wanted value and check if it is smaller than the Number.EPSILON. If true, then the value's error is smaller than the possible error of floating point arithmetic.
console.log([
[Math.sin(Math.PI), 0],
[Math.cos(Math.PI/2), 0],
[Math.sin(3.14), 0.0015926529164868282],
[Math.sin(3.141592), 6.535897930762419e-7]
].map(([a, b]) => Math.abs(a - b) < Number.EPSILON));
Some more to read about the problem with limited digital representation of floating point values:
Does “epsilon” really guarantees anything in floating-point computations?
Is floating point math broken?
Related
Since in Javascript all the numbers are double precision float is just a matter of he memory representation or numerical operation are as well all the same?
E.g. regarding computation complexity
15 / 3
14 / 3
would these operation cost the same computational resources or would v8 optimize integer devision case?
(V8 developer here.)
Short answer: It's complicated! And (as axiac points out) also not worth worrying about.
Long answer:
First off, when you have a division of number literals like 15 / 3 in your source, then V8 will constant-fold that at parsing time, so the division will only be performed once, and it doesn't really matter whether it's optimized in any way or not. For example, if you write function f() { return 15/3; }, then that will get compiled to function f() { return 5; }.
The next important observation is that the only way to tell whether a division will have an integer result is to actually perform the division and look at the result. Concretely, if an engine wanted to have something like:
function implementation_of_/_operator(x, y) {
if (division_result_will_be_integer(x, y)) {
return integer_division(x, y);
else {
return floating_point_division(x, y);
}
}
then it would have to implement division_result_will_be_integer somehow, for which there are two options:
function division_result_will_be_integer(x, y) {
if (!is_integer(x) || !is_integer(y)) return false;
return is_integer(floating_point_division(x, y));
}
// or:
function division_result_will_be_integer(x, y) {
if (!is_integer(x) || !is_integer(y)) return false;
(quotient, remainder) = integer_division_with_remainder(x, y);
return remainder == 0;
}
Clearly, performing a division just to decide which additional division to perform afterwards is silly, and it would be faster to skip that whole dance and just always do a floating-point division directly.
The third relevant point is that the hardware instruction for integer division can be quite slow. In particular, for large dividends and small divisors, it tends to be slower than floating-point division instructions. So what your question assumes to be an "optimization" may well reduce performance in practice.
Regardless of integer or floating-point domain, divisions are always fairly expensive operations. In case both operands are integers, divisions can be replaced by multiplications with the "multiplicative inverse" of the divisor. Finding this multiplicative inverse again involves a division though, so this technique only improves performance if you expect to perform many divisions with the same divisor -- such as when the divisor is a constant, e.g. f(x) { return x / 3; }. Also, operating on integers means that only integer results can be represented; if someone called f(14) in this example, then the multiplication-by-inverse technique would produce an incorrect result.
V8 uses this approach in optimized code if (1) the divisor is a constant and (2) at the time of optimizing the given function, all results it's previously seen produced at this particular division were integers. Such optimized code must then still contain a check to verify that all future results are also integers, i.e. it must check that division_result * dividend === divisor, and otherwise bail out to a floating-point division.
Lastly, there's the somewhat special handling of asm.js-style code. If you write f(x, y) { return ((x | 0) / (y | 0) | 0); }, then V8 will use an integer division instruction in that function. Obviously, the |0 operations mean that this function truncates both inputs and its result to 32-bit integers, which may or may not be acceptable for your use cases. Whether this will be faster or slower than a plain simple worry-free function f(x, y) { return x / y; } also depends on your use cases.
I've got two numbers that I want to compare. The numbers in the following example are the result of 26^26 computed in two different systems. One of which is my javascript code.
However, when comparing the two numbers I end up with something like this:
AssertionError [ERR_ASSERTION]: 4.0329146112660565e+26 == 4.0329146112661e+26
They're obviously not equal, but theoretically they should.
What's the proper way to perform equality on big numbers in javascript (even if it's an approximation)?
If what you're trying to do is determine if two numbers are practically equivalent you'll have to come up with your margin of error. One way to do this is to compute the difference between the numbers and then determine if that difference is significant or not.
So, taking your numbers from before, we could evaluate the difference between these numbers through subtraction. Since we don't really care about the sign of this difference, I'll go ahead and get the absolute value of the difference.
Math.abs(4.0329146112660565e+26 - 4.0329146112661e+26) === 4329327034368
(Sidenote: Now is not the time to explain why, but the == operator in JavaScript has confusing and error-prone behavior, use === when you want to compare values.)
That difference is a HUGE number, but related to how big our numbers are in the first place, it's rather insignificant. Intuitively, I'm tempted to divide the difference by the smallest of our original numbers like so:
4329327034368 / 4.0329146112660565e+26 === 1.0734983136696987e-14
That looks like a pretty small number. Repeat that same operation with a bunch of values and you should be able to determine what you want your margin of error to be. Then, all you'll have to do is perform the same operations with arbitrary numbers and see if that "difference ratio" is small enough for you.
function similar(a, b) {
let diff = Math.abs(a - b);
let smallest = Math.min(Math.abs(a), Math.abs(b));
let ratio = diff / smallest;
return ratio < MARGIN_OF_ERROR;
}
Now I just came up with that way of determining the importance of the difference between two numbers. It might not be a very smart way to compute it, it might be appropriate to some situations and not to others. But the general idea is that you'll have to make a function that determines if two values are close enough with your own definition of "close".
Be aware though, JavaScript is one of the worst languages you can be doing math in. Integers become imprecise when they go beyond Number.MAX_SAFE_INT (which seems to be 9007199254740991 according to Chrome, not sure if it varies between browsers or if that's a standardized constant).
Update: If your target engine is es2020 or above, you can use the new BigInt javascript primitive, for numbers higher than Number.MAX_SAFE_INTEGER
BigInt(4.0329146112660565e+26) === BigInt(4.0329146112661e+26)
//false
See more information in MDN
var a = 4.0329146112660565e+26;
var b = 4.0329146112661e+26;
a = Math.round(a/10e+20)*10e+20
b = Math.round(b/10e+20)*10e+20
a == b;
I would suggest to use one of big numbers library:
big.js (https://www.npmjs.com/package/big.js)
Example:
var x = new Big('4.0329146112660565e+26');
var y = new Big('4.0329146112661e+26');
// Should print false
console.log('Comparision result' + x.eq(y));
big-numbers (https://www.npmjs.com/package/big-numbers)
Example:
var x = bn.of('4.0329146112660565e+26');
var y = bn.of('4.0329146112661e+26');
// Should print false
console.log('Comparision result' + x.equals(y));
Writing some test cases for my Javascript program that deals with binary and right now I'm just using stringify to check if the value and expected values are equal:
JSON.stringify(val) === JSON.stringify(expected)
This works fine except for when I have floating point values. This is what happens:
Given Value: [10,20,30,32.400001525878906,{"test":3,"asdf":23}]
Expected Value: [10,20,30,32.4,{"test":3,"asdf":23}]
Test Failed!
So I guess I can't use stringify anymore to check if my two objects/arrays are equal. What's a good way to check if two potentially deeply nested objects/arrays are equal while also taking in to account floating point values? That is, two floating point values should be considered equal if they are 99.99% the same or whatever.
You'll need to test each element in the array in order, and you'll need to do it recursively for objects. This is typically known as a deep comparison or deep equality. You should be able to do this using a recursive function that checks the type(s) of the comparands.
When comparing floating point values, you'll want to use a tolerance. You do this by taking the absolute value of subtracting the two numbers from each other, and then comparing that to either a fixed tolerance value of your choosing, or a small number known as an epsilon.
In JavaScript, the machine epsilon is available as Number.EPSILON, and is defined to be the difference between 1 and the smallest number that is greater than 1 and can be represented as a Number. Similar constants are available in most languages and are typically used for tolerance-based comparisons.
Tolerance-based comparison turns floating point comparisons from simple equality into a subtract and compare. If you'd normally write
if (a === b) { ... }
you'd write that using the absolute value and a tolerance to eliminate floating point weirdness:
var tolerance = Number.EPSILON;
if (Math.abs(a - b) < tolerance) { ... }
If the difference between a and b is smaller than tolerance, you treat them as equal.
For a more nuanced (but possibly overkill for your case) approach, see The Floating Point Guide's section on comparison. The implementation presented there is in Java, but is likely portable to JavaScript without much effort.
This output should be true.but it give false always.
Number.isInteger(parseFloat('134965.83') / parseFloat('0.01'))
Floating point arithmetic in Javascript is broken and in general as well.
It has nothing to do with division, it will return false if you don't do division since you are checking float value.
Number.isInteger(parseFloat('134965.83') / parseFloat('0.01')) translates to Number.isInteger(13496582.999999998) -> false
Check these examples.
Number.isInteger(parseFloat('134965.83') )// outputs false without division
As per the spec
If Type(argument) is not Number, return false.
If floor(abs(argument)) ≠ abs(argument), return false.
This happens because the outcome of the division is not an integer but something like 13496582.999999998.
Some floating numbers require a very small precision that is limited by the data type used. For example, the number 1/3 can never be expressed entirely as 0.333333333333 because there is a limitation to the data type size. Therefore there will always be a tiny rounding error involved in floating operations.
Edit: In response to the comment asking for a recommendation on how to deal eith this, actually there are several possibilities. It depends on the context and on accuracy required.
In short, to overcome this use a very small constant Number.EPSILON (see also this) and use it in comparisons. Disclaimer: this is just a quick example, read extensively the implications on the links provided.
var myIsInteger = function(n) {
return (n % 1) > Number.EPSILON
};
We effectively check that the residual of the division with 1 is within the constant.
parseFloat('134965.83') / parseFloat('0.01') = 13496582.999999998
And when Number.isInteger(13496582.999999998) will always return false
Why is the Infinity property used as a command (rather than a result)
For example, this code below works, but the result isn't what I expected.
alert(isOdd(Infinity));
function isOdd(num) { return num%2==1; }
MDN REFERENCE
Infinity is a property of the global object, i.e. it is a variable in
global scope.
The initial value of Infinity is Number.POSITIVE_INFINITY. The value
Infinity (positive infinity) is greater than any other number. This
value behaves mathematically like infinity; for example, any positive
number multiplied by Infinity is Infinity, and anything divided by
Infinity is 0.
First what does this mean? In essence infinity is a concept not an actual value. Mathematics is based on concepts not values. For instance a number isn't a value, a numeral is.
The number 7 is the concept of the intended value, Romans wrote it as VII, in standard form (BASE-10) you write it as 7. In binary(BASE-2) you write it as 111. If you want to use a triangle or any other mark that is fine also as long as the concept is applied correctly.
Now that you know that, Infinity is simply the concept of being greater than any other number. It holds no value. The only reason that the basic concept of an infinity loops means to run forever is because in concept it means that whatever numeral iteration of that loop you are in (whether 1 or a million) infinity will always be greater than that number.
There are many methods to applying concepts in coding which is why everyone's code is ran differently but for example:
SAMPLE TAKEN FROM w3schools:
function findMax(x) {
var i;
var max = -Infinity;
for(i = 0; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
document.getElementById("demo").innerHTML = findMax(1, 123, 500, 115, 44, 88);
In the site's example they pass the argument of 6 values to the function findMax
findMax(1, 123, 500, 115, 44, 88);
They are then using a loop to stop at the parameters length. In the loop they are reassigning the max value from the concept of infinity to a value and if greater than that value when looped again the max value is then changed to the new high value.
Why is this important? Because in the example they use the concept of negative infinity which is simply the values of infinity decremented negatively. One could easily argue that 0 could replace -Infinity but they'd be wrong. This is why.
What if your value range is dependent upon negative values also being passed in the formula above? What if all you have is negative values that were dynamically captured from user input or another function?
Consider findMax was findMax(-1, -10, -15, -20);
0 would give a false output that it was the correct max value which wouldn't be what you wanted. You'd want -1 one to be the output. There are other methods to achieving the solution but for the sake of Infinity concept discussion I will end here.
I hope this sheds more light on the process of Infinity concept.
Infinity is a property of the global object that holds a numeric value representing the mathematical concept of infinity. I don't know any normal definition by which it could be called a "command."
With regard to your edit, that should return false (I ran it to confirm this suspicion, and it did on my browser). This is correct, as infinity is not normally considered an odd number.