I think it's time get some second opinions on the javascript I'm working on at the moment.
I'm trying to create a calculator to tell people if they can save money by using a subscription etc etc. The calculation itself is done by som inputs from the client and some prevalues from Umbraco CMS.
The result I get from the calculator at the moment is "right" in that the actual numbers are correct, but there's just too many zeroes in it.
The calculator can be found here: my calculator
The test data I'm using is the following:
Antal ansatte: 4
Gennemsnitlig ordreværdi kr. (ca.): 400
Antal ordrer årligt (ca.): 5500
Overskudsgrad (hvad er det?): 2.7
Which gives the output: 712800.0000000001
I tried to divide this by 100 and, of course, it just moved the comma/dot two steps the left. Still there's all those zeroes.
Any help/hint is greatly appreciated! :-)
Thanks in advance,
Bo
P.S. The result I'm looking for would be 7128.00
I believe you want to call toFixed on your integer.
(712800.00000001/100).toFixed(2)
"7128.00"
It will change your number into a string, but if it is for display purposes it should be fine.
You can do something like this:
value.toFixed(2);
This will round off all your trailing decimals to only 2.
You may want to use the round() method like this:
var val = Math.round(val*100)/100
This will give you the 2-decimal place precision you want, with rounding when needed.
Try this:
http://www.mredkj.com/javascript/nfbasic2.html
It is Number Format code for decimal places.
I suspect that you're running into floating point rounding errors (Is floating point math broken?). Try the solutions presented in Is there a definitive solution to javascript floating-point errors?.
Related
Might somebody already faced with calculation issue like in snippet below. First console command shows useless digits after calculation 10.1 +20.1 should be 30.2 but calculated as 30.200000000000003. and second one 10.2 + 20.2=30.4 is correct. There can be a lot of such decimal pairings which creates additional decimals in summ. Why does it happends and hove to avoid it?
console.log(10.1 + 20.1);
console.log(10.2 + 20.2);
This looks like a duplicate of How to deal with floating point number precision in JavaScript?.
You can use .toFixed(2) to always get a number with only 2 decimals. https://www.w3schools.com/jsref/jsref_tofixed.asp
More info: https://www.w3schools.com/js/js_numbers.asp
I have an issue trying to round some numbers to two digits.
I know it's not that complicated, I'm trying to do it this way:
console.log(parseFloat(3.4155113501943415e-303).toFixed(2))
console.log(parseFloat(8.224160000472033e-304).toFixed(2))
console.log(parseFloat(8.769850182148146e-304).toFixed(2))
But I have an issue with toFixed, it only returns 0.00 for all my numbers.
I suspect that it's due to that fact that my numbers are written this way:
3.4155113501943415e-303
8.224160000472033e-304
8.769850182148146e-304
etc.
With the e-304 at the end. Is it the issue? Do I have to delete that part or is there any way around it?
I think I saw a problem same as yours Parsing and converting exponential values to decimal in JavaScript. The problem is that 3.4155113501943415e-303 means three hundred zeros in front 0.0000..(and so on up to 300)..00000034155113501943415. So when you use toFixed(2) you get only 0.00. On the link I gave you there is a function which turns exponential number to double and then you can round it.
I just used toPrecision() and it worked. In the example they gave me they just removed the "e-n" which is just lazy in my opinion, we just don't know if it's e-343 or e-342 for example, which is a crazy thing to do.
Anyway, I've found the answer, thank you all!
When I pull the values I want to multiply, they're strings. So I pull them, parse them as floats (to preserve the decimal places), and multiply them together.
LineTaxRate = parseFloat(myRate) * parseFloat(myQuantity) * parseFloat(myTaxRateRound);
This has worked for 99% of my invoices but I discovered one very odd problem.
When it multiplied: 78 * 7 * 0.0725
Javascript is returning: 39.584999999999994
When you normally do the math in a calculator its: 39.585
When all is said and done, I take that number and round it using .toFixed(2)
Because Javascript is returning that number, it's not rounding to the desired value of: $39.59
I tried Math.round() the total but I still get the same number.
I have thought of rounding the number to 3 decimals then two, but that seems hacky to me.
I have searched everywhere and all I see is people mention parseFloat loses its precision, and to use .toFixed, however in the example above, that doesn't help.
Here is my test script i made to recreate the issue:
<script>
var num1 = parseFloat("78");
var num2 = parseFloat("7");
var num3 = parseFloat("0.0725");
var myTotal = num1 * num2 * num3;
var result = Math.round(myTotal*100)/100
alert(myTotal);
alert(myTotal.toFixed(2));
alert(result);
</script>
Floating points are represented in binary, not decimal. Some decimal numbers will not be represented precisely. And unfortunately, since Javascript only has one Number class, it's not a very good tool for this job. Other languages have decent decimal libraries designed to avoid precisely this kind of error. You're going to have to either accept one-cent errors, implement a solution server-side, or work very hard to fix this.
edit: ooh! you can do 78 * 7 * 725 and then divide by 10000, or to be even more precise just put the decimal point in the right place. Basically represent the tax rate as something other than a tiny fraction. Less convenient but it'll probably take care of your multiplication errors.
You might find the Accounting.js library useful for this. It has an "improved" toFixed() method.
JavaScript/TypeScript have only one Number class which is not that good. I have the same problem as I am using TypeScript. I solved my problem by using decimal.js-light library.
new Decimal(78).mul(7).mul(0.0725) returns as expected 39.585
I have an interesting question, I have been doing some work with javascript and a database ID came out as "3494793310847464221", now this is being entered into javascript as a number yet it is using the number as a different value, both when output to an alert and when being passed to another javascript function.
Here is some example code to show the error to its fullest.
<html><head><script language="javascript">alert( 3494793310847464221);
var rar = 3494793310847464221;
alert(rar);
</script></head></html>
This has completly baffeled me and for once google is not my friend...
btw the number is 179 more then the number there...
Your number is larger than the maximum allowed integer value in javascript (2^53). This has previously been covered by What is JavaScript's highest integer value that a Number can go to without losing precision?
In JavaScript, all numbers (even integral ones) are stored as IEEE-754 floating-point numbers. However, FPs have limited "precision" (see the Wikipedia article for more info), so your number isn't able to be represented exactly.
You will need to either store your number as a string or use some other "bignum" approach (unfortunately, I don't know of any JS bignum libraries off the top of my head).
Edit: After doing a little digging, it doesn't seem as if there's been a lot of work done in the way of JavaScript bignum libraries. In fact, the only bignum implementation of any kind that I was able to find is Edward Martin's JavaScript High Precision Calculator.
Use a string instead.
179 more is one way to look at it. Another way is, after the first 16 digits, any further digit is 0. I don't know the details, but it looks like your variable only stores up to 16 digits.
That number exceeds (2^31)-1, and that's the problem; javascript uses 32-bit signed integers (meaning, a range from –2,147,483,648 to 2,147,483,647). Your best choice is to use strings, and create functions to manipulate the strings as numbers.
I wouldn't be all too surprised, if there already was a library that does what you need.
One possible solution is to use a BigInt library such as: http://www.leemon.com/crypto/BigInt.html
This will allow you to store integers of arbitrary precision, but it will not be as fast as standard arithmetic.
Since it's to big to be stored as int, it's converted to float. In JavaScript ther is no explicit integer and float types, there's only universal Number type.
"Can't increment and decrement a string easily..."
Really?
function incr_num(x) {
var lastdigit=Number(x.charAt(x.length-1));
if (lastdigit!=9) return (x.substring(0,x.length-1))+""+(lastdigit+1);
if (x=="9") return "10";
return incr_num(x.substring(0,x.length-1))+"0";
}
function decr_num(x) {
if(x=="0") return "(error: cannot decrement zero)";
var lastdigit=Number(x.charAt(x.length-1));
if (lastdigit!=0) return (x.substring(0,x.length-1))+""+(lastdigit-1);
if (x=="10") return "9"; // delete this line if you like leading zero
return decr_num(x.substring(0,x.length-1))+"9";
}
Just guessing, but perhaps the number is stored as a floating type, and the difference might be because of some rounding error. If that is the case it might work correctly if you use another interpreter (browser, or whatever you are running it in)
I've searched through google (maybe I didn't look hard enough) but I could not find how to turn Math.sqrt into an int.
I want to use Math.sqrt for a for loop and I guess I need it as an int but I can't seem to figure out how to cast the result to an int. So how do I do it?
I tried something similar to Java:
(int) Math.sqrt(num);
But it didn't work.
Thanks in advance :)
Use Math.round, Math.ceil, or Math.floor depending on your specific rounding needs.
"For rounding numbers to integers one of Math.round, Math.ceil and Math.floor are preferable, and for a desired result that can be expressed as a 32 bit signed integer the bitwise operation described below might also suit."
-http://www.jibbering.com/faq/faq_notes/type_convert.html#tcNumber
Someone suggested parseInt. That goes from a string to an int, but it's easy to turn a float into a string.
parseInt(Math.sqrt(num)+"")
Remember that no matter what you do, JavaScript is always using floats. There is no integer type.
Math.floor will do it. Doubt you even need to go to an integer, though.
Math.floor(Math.sqrt(num));
Using parseInt(Math.sqrt(num)+"") is slower than using Math.round(Math.sqrt(num)). I think it is because in first example you are creating string, parsing integer value of num and rounding it. in second example you just take int and round it.
i know this is an old question, but i figure for anyone finding this later....
i won't reiterate what the other answers say, but a fun little trick you can do is:
Math.sqrt(2); //1.41......
~~Math.sqrt(2); //1
the double bitwise negative drops off anything after the decimal point. i've been told it's slightly faster, but i'm not entirely convinced.
EDIT: as a note this will round toward 0.