-
Notifications
You must be signed in to change notification settings - Fork 530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
toFixed error #53
Comments
Got the same error in my program -- total_amount = sum_results.invoice + sum_results.invoice * (results.customer.sales_tax.tax_rate / 100)
adjusted_payment_amount = accounting.toFixed(sum_results.new_payment, 2)
adjusted_total_amount = accounting.toFixed(total_amount, 2)
console.log "Total Amount: #{total_amount}"
console.log "Adjusted New Payment Amount: #{adjusted_payment_amount}"
console.log "Adjusted Total Amount: #{adjusted_total_amount}" yields
I would have thought that this would have rounded as well in this case. |
So, after some research, the problem is that some numbers can't be accurately described using Floating Points, which is what Javascript uses for Numbers. If you take a look at your numbers and how the toFixed function works, this is what happens: There seem to be two solutions; The first and probably preferred is to use a strong decimal variable type (http://jsfromhell.com/classes/bignumber). This wasn't acceptable in my case. So I had to turn to the (probably wrong) way of using what I guess is called an Epsilon Delta value. Basically, it's adding in an insignificant digit to the initial value to prevent the 999 repeating problem. I won't guarantee that this will work for you and I don't think this should be merged in master, but here's what I'm doing just the same. var toFixed = lib.toFixed = function(value, precision) {
precision = checkPrecision(precision, lib.settings.number.precision);
var power = Math.pow(10, precision);
var epsilon = typeof arguments[2] != 'undefined' ? arguments[2].substr(0,1).toLowerCase() : 'u';
// Determine rounding direction, multiply up by precision, round accurately, then divide and use native toFixed():
if (epsilon == "u") {
return (Math.round(lib.unformat(value + 0.00001) * power) / power).toFixed(precision);
} else if (epsilon == "d") {
return (Math.round(lib.unformat(value - 0.00001) * power) / power).toFixed(precision);
} else {
return (Math.round(lib.unformat(value) * power) / power).toFixed(precision);
}
}; It takes a third optional argument of 'epsilon', if it's "u" it will round up (and properly round your 35.245 to 35.25). I think that adding in such an insignificant digit won't affect the actual rounding of the number, but I've only tested that my use-cases work correctly. We probably need a bonafide mathematician in here to tell me that I'm wrong and my code should burn in hell, but hey...it works for me. |
I went back to something like |
I'm experiencing the same: http://jsfiddle.net/XyaC6/ |
the toFixed function is still broken right? it promises classical rounding but I get: accounting.toFixed(158.605, 2) = 158.60 Thanks |
It's not that it's 'broken', but this library doesn't use a strong decimal type because Javascript uses floating point arithmetic. So this is a constraint on the language, not the library. Take a look at my post above for more information and a potential workaround #53 (comment) |
I know about base 2 rounding problems etc, but the homepage claims: "Implementation of toFixed() that treats floats more like decimal values than binary, fixing inconsistent precision rounding in JavaScript (where some .05 values round up, while others round down):" So yes.. it's broken, because it fails to deliver what it promises. |
…version number
This was my fault. I fixed the bug, but only in the js, not in the min.js. I just updated my pull request (#75) to include the min.js and bumped the version number. |
I've downloaded the minified version from your branch and now is fixed! Thanks @stevenbristol |
Thanks, this is fixed by #164. |
I got this:
I should be getting 35.18, right?
The text was updated successfully, but these errors were encountered: