Currency Math in JavaScript - javascript

Can someone please help me out with a JavaScript/jQuery solution for this arithmetic problem:
I need to subtract one number from the other.
The problem is that the numbers have a dollar sign (because its money), therefore jQuery is treating them as strings instead of numbers.
I have created two variables - toalAssets and totalLiabilites. I would like to subtract the latter from the former and place the result into another variable called netWorth.
Perhaps i need to use parseFloat()?
But I'm not sure how - This is all a little over my head!

var totalLiabilites = '$52.34';
var toalAssets = '$85.12';
var pattern = /[^0-9.-]+/g;
var result = parseFloat(toalAssets.replace(pattern, '')) -
parseFloat(totalLiabilites.replace(pattern, ''));
// result: 32.78
Note: In JavaScript it is recommended1 to handle money as an integer representing the number of cents (8512 instead of 85.12). This is to avoid problems with floating-point arithmetic. 0.1 + 0.2 == 0.3 returns false in JavaScript, but fortunately integer arithmetic in floating point is exact, so decimal representation errors can be avoided by scaling.
You may want to check the following post for further reading on this topic: Is JavaScript’s math broken?
You can always apply the currency-sign formatting when the values are rendered to the browser.
1Douglas Crockford: JavaScript: The Good Parts: Appendix A - Awful Parts (page 105).

parseFloat() won't work because your string begins with a non-number, the dollar sign.
You can simply do a replace to remove the dollar sign, along with a parseFloat to get the value:
totalAssets = parseFloat(totalAssets.replace('$', ''));
totalLiabilities = parseFloat(totalLiabilities.replace('$', ''));
var difference = '$' + (totalAssets - totalLiabilities);
This code replaces your original strings with floats. You could load them into new variables as well. Likewise, difference does not have to have the '$' prepended.

var a = "$20";
var b = "$34";
var c = parseFloat(a.replace(/[^0-9\.]+/g, "")) - parseFloat(b.replace(/[^0-9\.]+/g, ""));
alert(c);

Related

parseFloat causing weird calculations

I have a function that needs to find the difference between 3 numbers. They can come in as strings, so I need to use parseFloat and maintain 2 decimal places. When I use parseFloat with negative numbers, I'm getting weird differences though.
// This will output -0.004999999999636212
let temp = -8985.69 - -8985.915 - 0.23
console.log(temp);
// But this will output -4.365674488582272e-13
let x = -8985.69
let y = -8985.915
let z = 0.23
let temp2 = parseFloat(x.toFixed(2)) - parseFloat(y.toFixed(2)) - parseFloat(z.toFixed(2))
console.log(temp2);
I was looking at the parseFloat docs and I see the part where the conversion may get changed when an invalid character is encountered. But I'm not seeing any wrong characters here and I'm not getting how the parsing stopping at any point would cause it to equal -4.365674488582272e-13
You second number has three decimal places and you set it toFixed(2) so it changes its value to -8985.92. When I use .toFixed(3) for it I get the first result you are looking for.
y = -8985.915
y.toFixed(2) => -8985.92
You need to read David Goldberg's 1991 paper, What Every Computer Scientist Should Know About
Floating-Point Arithmetic
And visit this web site: What Every Programmer Should Know About Floating-Point Arithmetic, or, Why don’t my numbers add up?

How can i get the same number value as given in JavaScript?

I got a number 1267508826984464384 from json response. Here i print the number.
<script>
var num = 1267508826984464384;
console.log(num);
var num = "1267508826984464384";
console.log(num);
</script>
output is
In the first print the output is different from the original value. I need the same value as given.
Is it possible?
JavaScript uses floating point under the hood to store numbers. Floating point double precision, which is what JavaScript uses, can only store 64 bits of data. With the way numbers are represented in this manner, this means that there's a limit to how big a Number can normally be (2^53 - 1 for double precision floating point). Your number in the example has gone over this limit (overflow) and hence is being rounded by JavaScript.
You can use BigInt:
var num = BigInt(1267508826984464384);
console.log(num); // logs 1267508826984464384n, with n representing that it's a BigInt type
var num = "1267508826984464384";
console.log(num); // logs 1267508826984464384
May be helpful to read What Every Programmer Should Know About Floating-Point Arithmetic for more information on why this is the case.
They are different types (int and string, respectfully). What you are seeing in the top example is integer overflow (safely abstracted by JS). You can use a big integer to bypass this issue
const hugeString = BigInt("1267508826984464384")
console.log(hugeString + 1n) // 1267508826984464385n
The type of this is BitInt and it will safely allow you to represent your number as a integer. This type must be treated different and the additions must also be BigInt (as shown in the example above).
BigInt is a built-in object that provides a way to represent whole numbers larger than 253 - 1, which is the largest number JavaScript can reliably represent with the Number primitive and represented by the Number.MAX_SAFE_INTEGER constant. BigInt can be used for arbitrarily large integers.
From MDN. You can use it like so:
const theBiggestInt = 9007199254740991n
const alsoHuge = BigInt(9007199254740991)
// ↪ 9007199254740991n
const hugeString = BigInt("9007199254740991")
// ↪ 9007199254740991n
const hugeHex = BigInt("0x1fffffffffffff")
// ↪ 9007199254740991n
const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111")
// ↪ 9007199254740991n
RegEx for finding numbers and quoting them. Looks for prop value boundaries and a sequence of digits and optionally one period, and replaces inserting with quotes around the number value.
RegEx should be adjusted for maximum length or tolerances for numbers to be quoted as strings.
key or value prefix/suffix can be added, so that a JSON.parse reviver function can recognize them and parse to big.js or BigInt.
In most cases, you probably already know if you might receive a large number, and could probably just use a trivial RegEx replace on the specific property you need.
And, you should be coordinating with the server-side to give the data to you in another form that is safe to consume.
Parsing number strings using BigInt and big.js.
str = String.raw `{"j\"son":1234561251261262131231231231231231231231231232123123123,
"array":
[123123123124124214124124124124.111,
124124124124124124124124124,
124124124124124124124124
]}
`
str = str.replace(/((?:{|,|\[)\s*(?:"(?:[^"]|\\")+"\s*:\s*)?)(\d+\.?\d*)(\s*)(?=,|}|\])/g, `$1"$2"$3`)
// note: capture group $3 is just whitespace, which can normally be ignored; included to be "technically accurate"
console.log(
str,
(BigInt(JSON.parse(str)[`j"son`]) + 1n).toString(),
(Big(JSON.parse(str).array[0]).plus(0.0003)).toFixed()
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/big.js/5.2.2/big.min.js" integrity="sha256-gPNmhPlEOUlyAZomtrYRW/HSIjBOOl2LVxft3rsJpxI=" crossorigin="anonymous"></script>

Tax and Javascript rounding issue [duplicate]

In the interest of creating cross-platform code, I'd like to develop a simple financial application in JavaScript. The calculations required involve compound interest and relatively long decimal numbers. I'd like to know what mistakes to avoid when using JavaScript to do this type of math—if it is possible at all!
You should probably scale your decimal values by 100, and represent all the monetary values in whole cents. This is to avoid problems with floating-point logic and arithmetic. There is no decimal data type in JavaScript - the only numeric data type is floating-point. Therefore it is generally recommended to handle money as 2550 cents instead of 25.50 dollars.
Consider that in JavaScript:
var result = 1.0 + 2.0; // (result === 3.0) returns true
But:
var result = 0.1 + 0.2; // (result === 0.3) returns false
The expression 0.1 + 0.2 === 0.3 returns false, but fortunately integer arithmetic in floating-point is exact, so decimal representation errors can be avoided by scaling1.
Note that while the set of real numbers is infinite, only a finite number of them (18,437,736,874,454,810,627 to be exact) can be represented exactly by the JavaScript floating-point format. Therefore the representation of the other numbers will be an approximation of the actual number2.
1 Douglas Crockford: JavaScript: The Good Parts: Appendix A - Awful Parts (page 105).
2 David Flanagan: JavaScript: The Definitive Guide, Fourth Edition: 3.1.3 Floating-Point Literals (page 31).
Scaling every value by 100 is the solution. Doing it by hand is probably useless, since you can find libraries that do that for you. I recommend moneysafe, which offers a functional API well suited for ES6 applications:
const { in$, $ } = require('moneysafe');
console.log(in$($(10.5) + $(.3)); // 10.8
https://github.com/ericelliott/moneysafe
Works both in Node.js and the browser.
There's no such thing as "precise" financial calculation because of just two decimal fraction digits but that's a more general problem.
In JavaScript, you can scale every value by 100 and use Math.round() everytime a fraction can occur.
You could use an object to store the numbers and include the rounding in its prototypes valueOf() method. Like this:
sys = require('sys');
var Money = function(amount) {
this.amount = amount;
}
Money.prototype.valueOf = function() {
return Math.round(this.amount*100)/100;
}
var m = new Money(50.42355446);
var n = new Money(30.342141);
sys.puts(m.amount + n.amount); //80.76569546
sys.puts(m+n); //80.76
That way, everytime you use a Money-object, it will be represented as rounded to two decimals. The unrounded value is still accessible via m.amount.
You can build in your own rounding algorithm into Money.prototype.valueOf(), if you like.
Unfortunately all of the answers so far ignore the fact that not all currencies have 100 sub-units (e.g., the cent is the sub-unit of the US dollar (USD)). Currencies like the Iraqi Dinar (IQD) have 1000 sub-units: an Iraqi Dinar has 1000 fils. The Japanese Yen (JPY) has no sub-units. So "multiply by 100 to do integer arithmetic" isn't always the correct answer.
Additionally for monetary calculations you also need to keep track of the currency. You can't add a US Dollar (USD) to an Indian Rupee (INR) (without first converting one to the other).
There are also limitations on the maximum amount that can be represented by JavaScript's integer data type.
In monetary calculations you also have to keep in mind that money has finite precision (typically 0-3 decimal points) & rounding needs to be done in particular ways (e.g., "normal" rounding vs. banker's rounding). The type of rounding to be performed might also vary by jurisdiction/currency.
How to handle money in javascript has a very good discussion of the relevant points.
In my searches I found the dinero.js library that addresses many of the issues wrt monetary calculations. Haven't used it yet in a production system so can't give an informed opinion on it.
use decimaljs ... It a very good library that solves a harsh part of the problem ...
just use it in all your operation.
https://github.com/MikeMcl/decimal.js/
Your problem stems from inaccuracy in floating point calculations. If you're just using rounding to solve this you'll have greater error when you're multiplying and dividing.
The solution is below, an explanation follows:
You'll need to think about mathematics behind this to understand it. Real numbers like 1/3 cannot be represented in math with decimal values since they're endless (e.g. - .333333333333333 ...). Some numbers in decimal cannot be represented in binary correctly. For example, 0.1 cannot be represented in binary correctly with a limited number of digits.
For more detailed description look here: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Take a look at the solution implementation: http://floating-point-gui.de/languages/javascript/
Due to the binary nature of their encoding, some decimal numbers cannot be represented with perfect accuracy. For example
var money = 600.90;
var price = 200.30;
var total = price * 3;
// Outputs: false
console.log(money >= total);
// Outputs: 600.9000000000001
console.log(total);
If you need to use pure javascript then you have need to think about solution for every calculation. For above code we can convert decimals to whole integers.
var money = 60090;
var price = 20030;
var total = price * 3;
// Outputs: true
console.log(money >= total);
// Outputs: 60090
console.log(total);
Avoiding Problems with Decimal Math in JavaScript
There is a dedicated library for financial calculations with great documentation. Finance.js
Use this code for currency calculation and round numbers in two digits.
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Variables</h1>
<p id="test1"></p>
<p id="test2"></p>
<p id="test3"></p>
<script>
function setDecimalPoint(num) {
if (isNaN(parseFloat(num)))
return 0;
else {
var Number = parseFloat(num);
var multiplicator = Math.pow(10, 2);
Number = parseFloat((Number * multiplicator).toFixed(2));
return (Math.round(Number) / multiplicator);
}
}
document.getElementById("test1").innerHTML = "Without our method O/P is: " + (655.93 * 9)/100;
document.getElementById("test2").innerHTML = "Calculator O/P: 59.0337, Our value is: " + setDecimalPoint((655.93 * 9)/100);
document.getElementById("test3").innerHTML = "Calculator O/P: 32.888.175, Our value is: " + setDecimalPoint(756.05 * 43.5);
</script>
</body>
</html>

Translation into another number system JS

I have a string and I need to convert this string into another number system.
1959113774617397110401052 - in Decimal notation to thirty-tensary number system (10 to 36).
If i try to use this code:
var master = 1959113774617397110401052;
parseInt(master, 10).toString(36);
//8v0wc05bcz000000
It doesn't work properly.
Can you help me to know, where is my mistake and how to use this correctly.
Thank you!
The maximum integer JavaScript can safely handle is 9007199254740991. This is what we get if we call Number.MAX_SAFE_INTEGER. Your number, on the other hand, is significantly larger than this:
9007199254740991
1959113774617397110401052
Because of this, JavaScript isn't able to safely perform mathematical calculations with this number and there's no guarantee that you'll get an accurate result.
The MAX_SAFE_INTEGER constant has a value of 9007199254740991. The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent numbers between -(253 - 1) and 253 - 1.
Safe in this context refers to the ability to represent integers exactly and to correctly compare them. For example, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 will evaluate to true, which is mathematically incorrect. See Number.isSafeInteger() for more information.
— MDN's notes on Number.MAX_SAFE_INTEGER
You would need to use a multi-precision library like Decimal.js for integer calculations that exceed the range of signed Int32 resp. the continuous integer range representable by 64bit floats. As example:
var astr = '1959113774617397110401052'
var a =new Decimal(astr)
var out = '';
while( a > 0 ) {
var d = a.mod(36).toNumber();
a = a.divToInt(36);
if(d>9) d=d+39; // d+7 for upper case
out = String.fromCharCode(48+d)+out
}
var my_div = document.getElementById("my_div")
my_div.innerHTML += astr+" in base 36 is "+out;
<script src="https://raw.githubusercontent.com/MikeMcl/decimal.js/master/decimal.min.js"></script>
<div id="my_div"></div>

Javascript : How to increase a fraction value in a textbox ? example: 0.10 to 0.11 [duplicate]

This question already has answers here:
How to add two strings as if they were numbers? [duplicate]
(20 answers)
how to sum two numbers from input tag? [duplicate]
(2 answers)
Closed 9 years ago.
I need to increase a fraction in a text box
using javascript.
the goal is to add 1 penny until it is 0.99
and then it will be 1.00 and 1.01
how can this be done in javascript?
this is what is not working.
var a;
a = document.getElementById('a1').value;
a = a+a;
alert(a);
alert returns
0.100.10
Additional Info
var a;
a = parseFloat(document.getElementById('b13').value);
a = a+a;
alert(a);
returns
0.2
i would rather see 0.20
but most importantly, how do increase this by 0.01 at a time ?
SOLVED:
both
var a;
a = parseFloat(document.getElementById('a1').value);
a = a+0.01;
alert(a);
}
and ...
document.getElementById('a1').value = +document.getElementById('a1').value + 0.01
worked fine.
Text box returns the value as string so parse it
var a;
a = parseFloat(document.getElementById('a1').value);
a = (a+a).toFixed(2);
alert(a);
And it doesn't adds 0.01 to a .. It doubles the a so use something like this.
var a;
a = parseFloat(document.getElementById('a1').value);
a = (a + 0.01).toFixed(2);
alert(a);
a = a+a doesn't add .01. It would double a if a was a number, but since javascript is seeing it as a string, it just concatenates it.
You want a = +a+0.01.
This will add 0.01 to the value of a. The initial + is to make sure that javascript treats a as a number instead of a string.
This will work fine for your alert, but then you still need to set the value back:
document.getElementById('a1').value = a
Or, to put it all in one line (using the toFixed addition from HMR):
document.getElementById('a1').value = (+document.getElementById('a1').value + 0.01).toFixed(2)
First convert a into float like this,
a = parseFloat(document.getElementById('a1').value);
Then add and convert a to float like this,
a = (a + a).toFixed(2)
and alert the answer.
a is containing a string, instead of a number. string + string returns the concatenation of the two strings - you haven't told Javascript it's a number, so it doesn't treat it like one.
You can use parseFloat and parseInt to turn strings into floating point numbers (have decimal places) or integers (do not). http://www.javascripter.net/faq/convert2.htm
However, be aware that floating point numbers have inaccuracies due to being stored in limited amount of memory - they will round off after a certain number of places (and not decimal places - binary places, for example 0.1 cannot be represented exactly as a floating point number, despite being only one decimal place in base 10!), and if you need to do important financial calculations, you should be aware of this inaccuracy (for example, you might use a fixed point number system instead). Read What Every Computer Scientist Should Know About Floating-Point Arithmetic for more information.

Categories