Is there a way to truncate scientific notation numbers in Javascript? - javascript

As you all know since it is one of the most asked topic on SO, I am having problems with rounding errors (it isn't actually errors, I am well aware).
Instead of explaining my point, I'll give an example of what possible numbers I have and which input I want to be able to obtain:
Let's say
var a = 15 * 1e-9;
alert(a)
outputs
1.5000000000000002e-8
I want to be able to obtain 1.5e-8 instead, but I cannot just multiply by 10e8, round and divide by 10e8 because I don't know if it will be e-8 or e-45 or anything else.
So basically I want to be able to obtain the 1.5000002 part, apply toFixed(3) and put back the exponent part.
I could convert into a string and parse but it just doesn't seem right...
Any idea ?
(I apologize in advance if you feel this is one of many duplicates, but I could not find a similar question, only related ones)
Gael

You can use the toPrecision method:
var a = 15 * 1e-9;
a.toPrecision(2); // "1.5e-8"

If you're doing scientific work and need to round with significant figures in mind: Rounding to an arbitrary number of significant digits

var a = 15 * 1e-9;
console.log(Number.parseFloat(a).toExponential(2));
//the above formula will display the result in the console as: "1.50e-8"

Related

Adding a whole number and a decimal in Javascript results in removal of the decimal?

I'm sure this is simple, but in my javascript code, I have two numbers. One contains a decimal, and the other doesn't, and I add them together (ie. 7.5 + 5), I am getting a result with NO decimal value.
Do I need to cast each number variable as a double? I know that all numbers are doubles in javascript - which is why I do not understand this behavior...
For instance, I have var answer = week1 + week2;. Does this make sense?
Thanks in advance!
I am sorry for wasting time - turns out I was using parseInt instead of parseFloat to gather the "week" values I spoke about.
Can someone please close this question or delete it? Before the shame consumes me?

Javascript error in toPrecision() function

I want to use toPrecision() to reduce the size of a number before I display it. However, I sometimes cannot multiply output of the function by another number without gaining a small rounding error. See the code sample below:
var x = 0.0197992182093305
alert (x.toPrecision(4)) //Correct: 0.01980
alert (Number(x.toPrecision(4))) //Correct: 0.0198
alert( Number(x.toPrecision(4)) * 100) //Incorrect: 1.9800000000000002
JSFiddle: http://jsfiddle.net/ueLsL460/4/ What's going on here?
Based on what I understand, Number(x.toPrecision(4)) * 100 creates a new Number object which will not inherit the precision of the parent.
If you still want it to be precise after Math, you need to put it in precision again.
alert((x * 100).toPrecision(4));
Technically, it's not an error. It's just the way javascript is supposed to work.
The use of primitive constructors is not that ideal, unless you are trying to do something trivial. Can you please try to do the code on the following fiddle and see if this will do for you?
http://jsfiddle.net/ueLsL460/5/
var x = 0.0197992182093305;
alert((x * 100).toPrecision(4));
Javascript doesn't have a decimal equivalent - so in your case floating points are used. What this means is that Number(x.toPrecision(4)) doesn't give you exactly 0.0198, but something the FP binary number closest to 0.0198. So any arithmetic you do will be subject to the loss of precision introduced in floating point arithmetic. You can see the same effect if you do
alert(0.0198 * 100);
By the way
alert(0.0198 * 10 * 10);
gives you no problem (the loss of precision does not build up enough to make it into the digits Javascript deems to display) - but that's for this particular number alone.

Parse json in javascript - long numbers get rounded

I need to parse a json that contains a long number (that was produces in a java servlet). The problem is the long number gets rounded.
When this code is executed:
var s = '{"x":6855337641038665531}';
var obj = JSON.parse(s);
alert (obj.x);
the output is:
6855337641038666000
see an example here: http://jsfiddle.net/huqUh/
why is that, and how can I solve it?
As others have stated, this is because the number is too big. However, you can work around this limitation by sending the number as a string like so:
var s = '{"x":"6855337641038665531"}';
Then instead of using JSON.parse(), you can use a library such as javascript-bignum to work with the number.
It's too big of a number. JavaScript uses double-precision floats for numbers, and they have about 15 digits of precision (in base 10). The highest integer that JavaScript can reliably save is something like 251.
The solution is to use reasonable numbers. There is no real way to handle such large numbers.
The largest number JavaScript can handle without loss of precision is 9007199254740992.
I faced this issue some time ago, I was able to solve using this lib: https://github.com/josdejong/lossless-json
You can check this example:
let text = '{"normal":2.3,"long":123456789012345678901,"big":2.3e+500}';
// JSON.parse will lose some digits and a whole number:
console.log(JSON.stringify(JSON.parse(text)));
// '{"normal":2.3,"long":123456789012345680000,"big":null}' WHOOPS!!!
// LosslessJSON.parse will preserve big numbers:
console.log(LosslessJSON.stringify(LosslessJSON.parse(text)));
// '{"normal":2.3,"long":123456789012345678901,"big":2.3e+500}'

Javascript .toFixed() more precise rounding alternative?

For rounding decimals (prices), I've been using .toFixed(2) for quite some time now. But I just recently discovered that Javascript can't "precisely" round decimals. I was a bit shocked that even 10.005 couldn't be rounded correctly to 10.01. It just got rounded down to 10.00. And other times it did round correctly. I like to have control over my code, so this is a big no-no for me.
And since I'm calculating prices, I think I need something more (100%) accurate for rounding only 2- or 3-decimal numbers, maybe a 4-decimal one.
Is there no straightforward way of doing basic rounding in javascript, the correct way?
UPDATE: As Felix Kling has suggested, the method of processing my prices as integers of cents, there are also drawbacks to this (besides more code)?
The reason that a number like 10.005 can't be rounded corretly is that you don't really have the number 10.005, you only have a number that is the closest possible one that can be represented using a double precision floating point variable.
The actual number that you have might be someting like 10.00499999999276253, and that would naturally round to 10.00 rather than 10.01.
To handle monetary values you should use a data type that can represent the value exactly. As numbers in Javascript are always floating point numbers, what you are left with is representing the numbers as text, and writing your own functions to do the math (or find someone who has done that already).
This should work for you, here's a fiddle to play around with it http://jsfiddle.net/5ffyC/1/
function moneyRound(flt){
var splitStr = flt.toString().split('.'),
whole = (flt * 100) | 0;
if (splitStr.length > 1 && splitStr[1].length > 2){
return splitStr[1][2] > 4? (whole + 1) / 100: whole / 100;
} else {
return flt;
}
}

Javascript issue with math calculations

Why is it if I do this in javascript, I get the following result:
1234.56 * 10 = 12345.599999999999
It should be 123456. How can I get around this problem?
Thanks.
Floating points are not exact, since there are ifinite numbers at their range [or in any range to be more exact], and only a finite number of bits to store this data.
Have a look at what every programmer should know about floating point arithmetics.
Another easy solution:
parseFloat((1234.56 * 10).toPrecision(12))
and the result will be: 12345.6, and YES... it works with decimal numbers.
As the others said, floating points and so on.
Easy solution would be to do something like this:
var answer = parseInt(1234.56 * 10);
Or just use Math.round?
All numbers in JS are internally defined by float and drop the less significant digits if needed.
(10000000000000000000000000000 + 1) == 10000000000000000000000000000
// this will return true
And javascript is well known for droping bits quite often in numbers. So handle with care

Categories

Resources