Subtracting 2 decimal numbers javascript - javascript

Hi im trying to subtract 2 decimal numbers and it keeps returning some weird number.
var x = 0.00085022
var y = 0.00085050
var answer = x - y
alert(answer)
This is the number its returning -2.8000000000007186e-7

The maximum number of decimals is 17, but floating point arithmetic is not always 100% accurate
http://www.w3schools.com/js/js_numbers.asp
Try this:
var x = 0.00085022 * 100000000;
var y = 0.00085050 * 100000000;
var answer = (x - y) / 100000000;
alert(answer);

You are subtracting with a higher number and the calculations are traversing to an even lower number. Yes -2.0 is lower and the decimal places precision is reaching exponentially higher.
If we round them up we get:
var x = 85022
var y = 85050
var answer = x - y
alert(answer); // = -28

Related

Calculating π using a Monte Carlo Simulation limitations

I have asked a question very similar to this so I will mention the previous solutions at the end, I have a website that calculates π with the client's CPU while storing it on a server, so far I've got:
'701.766.448.388' points inside the circle, and '893.547.800.000' in total, these numbers are calculated using this code. (working example at: https://jsfiddle.net/d47zwvh5/2/)
let inside = 0;
let size = 500;
for (let i = 0; i < iterations; i++) {
var Xpos = Math.random() * size;
var Ypos = Math.random() * size;
var dist = Math.hypot(Xpos - size / 2, Ypos - size / 2);
if (dist < size / 2) {
inside++;
}
}
The problem
(4 * 701.766.448.388) / 893.547.800.000 = 3,141483638
This is the result we get, which is correct until the fourth digit, 4 should be 5.
Previous problems:
I messed up the distance calculation.
I placed the circle's from 0...499 which should be 0...500
I didn't use float, which decreased the 'resolution'
Disclamer
It might just be that I've reached a limit but this demonstration used 1 million points and got 3.16. considering I've got about 900 billion I think it could be more precisely.
I do understand that if I want to calculate π this isn't the right way to go about it, but I just want to make sure that everything is right so I was hoping anyone could spot something wrong or do I just need more 'dots'.
EDIT: There are quite a few mentions about how unrealistic the numbers where, these mentions where correct and I have now updated them to be correct.
You could easily estimate what kind of error (error bars) you should get, that's the beauty of the Monte Carlo. For this, you have to compute second momentum and estimate variance and std.deviation. Good thing is that collected value would be the same as what you collect for mean, because you just added up 1 after 1 after 1.
Then you could get estimation of the simulation sigma, and error bars for desired value. Sorry, I don't know enough Javascript, so code here is in C#:
using System;
namespace Pi
{
class Program
{
static void Main(string[] args)
{
ulong N = 1_000_000_000UL; // number of samples
var rng = new Random(312345); // RNG
ulong v = 0UL; // collecting mean values here
ulong v2 = 0UL; // collecting squares, should be the same as mean
for (ulong k = 0; k != N; ++k) {
double x = rng.NextDouble();
double y = rng.NextDouble();
var r = (x * x + y * y < 1.0) ? 1UL : 0UL;
v += r;
v2 += r * r;
}
var mean = (double)v / (double)N;
var varc = ((double)v2 / (double)N - mean * mean ) * ((double)N/(N-1UL)); // variance
var stdd = Math.Sqrt(varc); // std.dev, should be sqrt(Pi/4 (1-Pi/4))
var errr = stdd / Math.Sqrt(N);
Console.WriteLine($"Mean = {mean}, StdDev = {stdd}, Err = {errr}");
mean *= 4.0;
errr *= 4.0;
Console.WriteLine($"PI (1 sigma) = {mean - 1.0 * errr}...{mean + 1.0 * errr}");
Console.WriteLine($"PI (2 sigma) = {mean - 2.0 * errr}...{mean + 2.0 * errr}");
Console.WriteLine($"PI (3 sigma) = {mean - 3.0 * errr}...{mean + 3.0 * errr}");
}
}
}
After 109 samples I've got
Mean = 0.785405665, StdDev = 0.410540627166729, Err = 1.29824345388086E-05
PI (1 sigma) = 3.14157073026184...3.14167458973816
PI (2 sigma) = 3.14151880052369...3.14172651947631
PI (3 sigma) = 3.14146687078553...3.14177844921447
which looks about right. It is easy to see that in ideal case variance would be equal to (Pi/4)*(1-Pi/4). It is really not necessary to compute v2, just set it to v after simulation.
I, frankly, don't know why you're getting not what's expected. Precision loss in summation might be the answer, or what I suspect, you simulation is not producing independent samples due to seeding and overlapping sequences (so actual N is a lot lower than 900 trillion).
But using this method you control error and check how computation is going.
UPDATE
I've plugged in your numbers to show that you're clearly underestimating the value. Code
N = 893_547_800_000UL;
v = 701_766_448_388UL;
v2 = v;
var mean = (double)v / (double)N;
var varc = ((double)v2 / (double)N - mean * mean ) * ((double)N/(N-1UL));
var stdd = Math.Sqrt(varc); // should be sqrt(Pi/4 (1-Pi/4))
var errr = stdd / Math.Sqrt(N);
Console.WriteLine($"Mean = {mean}, StdDev = {stdd}, Err = {errr}");
mean *= 4.0;
errr *= 4.0;
Console.WriteLine($"PI (1 sigma) = {mean - 1.0 * errr}...{mean + 1.0 * errr}");
Console.WriteLine($"PI (2 sigma) = {mean - 2.0 * errr}...{mean + 2.0 * errr}");
Console.WriteLine($"PI (3 sigma) = {mean - 3.0 * errr}...{mean + 3.0 * errr}");
And output
Mean = 0.785370909522692, StdDev = 0.410564786603016, Err = 4.34332975349809E-07
PI (1 sigma) = 3.14148190075886...3.14148537542267
PI (2 sigma) = 3.14148016342696...3.14148711275457
PI (3 sigma) = 3.14147842609506...3.14148885008647
So, clearly you have problem somewhere (code? accuracy lost in representation? accuracy lost in summation? repeated/non-independent sampling?)
any FPU operation will decrease your accuracy. Why not do something like this:
let inside = 0;
for (let i = 0; i < iterations; i++)
{
var X = Math.random();
var Y = Math.random();
if ( X*X + Y*Y <= 1.0 ) inside+=4;
}
if we probe first quadrant of unit circle we do not need to change the dynamic range by size and also we can test the distances in powered by 2 form which get rid of the sqrt. These changes should increase the precision and also the speed.
Not a JAVASCRIPT coder so I do not know what datatypes you use but you need to be sure you do not cross its precision. In such case you need to add more counter variables to ease up the load on it. For more info see: [edit1] integration precision.
As your numbers are rather big I bet you crossed the boundary already (there should be no fraction part and trailing zeros are also suspicious) For example 32bit float can store only integers up to
2^23 = 8388608
and your 698,565,481,000,000 is way above that so even a ++ operation on such variable will cause precision loss and when the exponent is too big it even stop adding...
On integers is this not a problem but once you cross the boundary depending on internal format the value wraps around zero or negates ... But I doubd that is the case as then the result would be way off from PI.

How many times can I multiple a number by a decimal/fraction before it reaches close to zero

I'm trying to determine how far ahead to check for a ledge based on an objects speed. This way the object can stop accelerating and let friction stop it.
the problem
friction is 0.9 * horizontalSpeed each step.
when horizontalSpeed is less than 0.001 we set the horizontalSpeed to 0
how long it takes to reach 0.001 is horizontalSpeed = 1
how im currently solving
var horizontalSpeed = 1
var friction = 0.9
var closeEnoughToZero = 0.001
var distance = 0
while(horizontalSpeed > closeEnoughToZero) {
horizontalSpeed *= friction
distance += horizontalSpeed
}
console.log(distance) // 8.99
Possible already the solution I just feel it is a bit brute force and likely some type of math function that is handy for this!
Here's a "pure maths" solution
var horizontalSpeed = 1
var friction = 0.9
var closeEnoughToZero = 0.001
var distance = (horizontalSpeed * friction)/(1-friction)
console.log(distance)
Or, given a "close enough to zero", that can be done without a loop too
var horizontalSpeed = 1
var friction = 0.9
var closeEnoughToZero = 0.001
var distance = 0
// this is the power you need to raise "friction" to, to get closeEnoughToZero
let n = Math.ceil(Math.log(closeEnoughToZero)/Math.log(friction));
// now use the formula for Sum of the first n terms of a geometric series
let totalDistance = horizontalSpeed * friction * (1 - Math.pow(friction, n))/(1-friction);
console.log(totalDistance);
I use the Math.ceil of Math.log(closeEnoughToZero)/Math.log(friction) - which in your case is 66. If you added a loop counter to your code, you'd see the loop executes 66 times
And, as you can see the second code produces exactly the same output as your loop.

How do I avoid or work around the floor function and incorrectly represented integers?

So I am trying to take a number that can be in any positive form and cut it to two decimal places. So for example I have an input of 145.26. However in my code this is being rounded down to 145.19. Here is the code I am using:
var multiplier = 100;
var adjustedNum = input * multiplier;
var truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum);
var fixedResult = truncatedNum / multiplier;
So basically my 'input' should become 145200. However it is actually becoming 145199.9999995 or something to that effect. This is causing the Math.floor method to round it down. Is there any way to workaround or avoid this?
Multiply the number by an additional factor of 10 to round it. Then divide it by 10 to apply the floor or ceil.
var multiplier = 100;
var adjustedNum = Math.round(input * multiplier * 10);
var truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum/10);
var fixedResult = truncatedNum / multiplier;

How can I round a decimal up to the nth decimal?

In JavaScript, I would like to round a given number (x) up based on another decimal (y). For example:
x = 8.6333
y = 0.5
result = 9
x = 8.6333
y = 0.2
result = 8.8
x = 8.6333
y = 0.1
result = 8.7
How would I go about doing this?
Divide x by the y. Round that up, and multiply by y again.
var answer = Math.ceil(x/y)*y;

Javascript: Precision strange behavior [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is JavaScript's Math broken?
Suppose,
var x = .6 - .5;
var y = 10.2 – 10.1;
var z = .2 - .1;
Comparison result
x == y; // false
x == .1; // false
y == .1; // false
but
z == .1; // true
Why Javascript show such behavior?
Because floating point is not perfectly precise. You can end up with slight differences.
(Side note: I think you meant var x = .6 - .5; Otherwise, you're comparing -0.1 with 0.1.)
JavaScript uses IEEE-754 double-precision 64-bit floating point (ref). This is an extremely good approximation of floating point numbers, but there is no perfect way to represent all floating point numbers in binary.
Some discrepancies are easier to see than others. For instance:
console.log(0.1 + 0.2); // "0.30000000000000004"
There are some JavaScript libraries out there that do the "decimal" thing a'la C#'s decimal type or Java's BigDecimal. That's where the number is actually stored as a series of decimal digits. But they're not a panacea, they just have a different class of problems (try to represent 1 / 3 accurately with it, for instance). "Decimal" types/libraries are fantastic for financial applications, because we're used to dealing with the style of rounding required in financial stuff, but there is the cost that they tend to be slower than IEEE floating point.
Let's output your x and y values:
var x = .6 - .5;
console.log(x); // "0.09999999999999998"
var y = 10.2 - 10.1;
console.log(y); // "0.09999999999999964"
No great surprise that 0.09999999999999998 is != to 0.09999999999999964. :-)
You can rationalize those a bit to make the comparison work:
function roundTwoPlaces(num) {
return Math.round(num * 100) / 100;
}
var x = roundTwoPlaces(0.6 - 0.5);
var y = roundTwoPlaces(10.2 - 10.1);
console.log(x); // "0.1"
console.log(y); // "0.1"
console.log(x === y); // "true"
Or a more generalized solution:
function round(num, places) {
var mult = Math.pow(10, places);
return Math.round(num * mult) / mult;
}
Live example | source
Note that it's still possible for accuracy crud to be in the resulting number, but at least two numbers that are very, very, very close to each other, if run through round with the same number of places, should end up being the same number (even if that number isn't perfectly accurate).

Categories