Last active
April 27, 2017 17:02
-
-
Save alexitaylor/1550400a047cf8ae614499eedbc12861 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Prompt: tackling floating-point imprecision with the CashAmount class | |
In programming languages such as JavaScript, 0.1 + 0.2 does not equal 0.3. This is true in Ruby, Python, etc. The imprecision is inherent in floating-point arithmetic, it isn't because JavaScript itself is wonky. | |
These tiny errors can add up and cause actual wrong answers over time if you're not careful. They also make it harder to unit-test your work, since you have to compare within ranges rather than comparing to exact expected values. | |
To deal with this specifically within a monetary context, let's make a class called CashAmount that accepts double values (e.g., 14.72) and will never suffer from the aforementioned precision problems. A CashAmount represents a collection of bills and coins, such as you might find in your wallet, purse, or a cash register. | |
Note: you can do this by converting to pennies for all denominations so you are always working with integers, then converting back to a two-decimal float as needed. */ | |
const CashAmount = function(value) { | |
this.value = value; | |
}; | |
CashAmount.prototype.totalInPennies = function() { | |
return parseInt(parseFloat(this.value).toFixed(2).toString().replace('.', '')) | |
} | |
CashAmount.prototype.addDoubleAmount = function(addTo) { | |
this.value += addTo; | |
} | |
CashAmount.prototype.toDouble = function() { | |
return this.value.toFixed(2) | |
} | |
CashAmount.prototype.toDoubleString = function() { | |
return this.value.toString() | |
} | |
CashAmount.prototype.quantityOfEachDenomination = function() { | |
var quantity = { | |
'hundreds': 0, | |
'fifties': 0, | |
'twenties': 0, | |
'tens': 0, | |
'fives': 0, | |
'ones': 0, | |
'quarters': 0, | |
'dimes': 0, | |
'nickels': 0, | |
'pennies': 0 | |
} | |
var amtArray = [100, 50, 20, 10, 5, 2, 1, .25, .10, .05, .01]; | |
for (var i = 0; i <= amtArray.length; i++) { | |
console.log(parseInt(value / amtArray[i])) | |
//console.log(value % amtArray[i]); | |
} | |
} | |
const cash = new CashAmount(10.50); | |
console.log(cash.totalInPennies()); // -> 1050 | |
cash.addDoubleAmount(29.33); | |
console.log(cash.totalInPennies()); // -> 3983 | |
console.log(cash.toDouble()); // -> 39.83) | |
console.log(cash.toDoubleString()); // -> '39.83') | |
const moreCash = new CashAmount(0.10); | |
moreCash.addDoubleAmount(0.20); | |
console.log(0.10 + 0.20 === 0.30); // -> false | |
console.log(moreCash.totalInPennies() === 30); // -> true | |
const moarCash = new CashAmount(967.93); | |
moarCash.quantityOfEachDenomination() // -> | |
var expected = { | |
'hundreds': 9, | |
'fifties': 1, | |
'twenties': 0, | |
'tens': 1, | |
'fives': 1, | |
'ones': 2, | |
'quarters': 3, | |
'dimes': 1, | |
'nickels': 1, | |
'pennies': 3 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment