Convert dollars to cents in JavaScript - javascript

I am trying to convert $3.77 (USD) to cents as follows:
const number = "3.77"
const separe = number.replace(".", "")
Is that the correct way to convert USD to cents? because I have seen some reports with different code and not which one is correct, any ideas?

Be careful when doing arithmetic calculation in JavaScript. Especially if you are dealing with floating point.
Consider this case:
+19.99 * 100 // 1998.9999999999998
19.99 * 100 // 1998.9999999999998
parseFloat(19.99) * 100 // 1998.9999999999998
I know, right?! So I made this simple helper to help you out:
const toCent = amount => {
const str = amount.toString()
const [int] = str.split('.')
return Number(amount.toFixed(2).replace('.', '').padEnd(int.length === 1 ? 3 : 4, '0'))
}
Result:
toCent(19.99) // 1999
toCent(19.9) // 1990
toCent(1.9) // 190
toCent(1999.99) // 199999
I haven't tested it yet thoroughly. Please don't copy paste my solution, at least you do your own test.

The way you are doing it now is perfectly valid. I have benchmarked your answer vs the answers from the comments and here are the results.
Winner:
const result = (parseFloat(number) * 100).toString();
Second Place (~99% of Winner):
const result = (Number(number) * 100).toString();
Third Place (~96% of Winner):
const result = (+number * 100).toString();
Fourth Place (~80% of Winner):
const result = number.replace(".", "");
As noted, your method will not work when the string does not match /\d\.\d\d/ however the other methods will work.
Tested on Safari 14

This will do it with any value.
export function toCents(aValue){
return Math.round((Math.abs(aValue) / 100) * 10000);
}

Math.round(x * 100) seems pretty safe because it will round to the nearest integer. The better options are:
Always represent your amounts in cents (i.e. whole numbers) and divide into dollars when needed
Use a library (such as decimal.js or Big.js)
The implementations in the above two libraries are super complex (here, here).

Related

Can I use variables in JS `e` numbers?

Per 'e' in javascript numbers I would like to use 'e' notation:
Right now I'm doing:
const USD_DECIMALS = 2
const USD = 1e2
As you can see I'm duplicating the number 2. When I'd like to do is something like:
const USD_DECIMALS = 2
const USD = 1e[USD_DECIMALS]
Is this possible? Maybe using the Number() constructor or similar?
You could make a string out of "1e2" and then run it through Number.
const USD_DECIMALS = 2
const USDString = `1e${USD_DECIMALS}`;
const USD = Number(USDString);
console.log(USD);
Not directly (without building a dynamic string, but then that's not direct either), but since 1e2 means 1 times 10², you can use either 1 * Math.pow(10, USD_DECIMALS) OR 1 * 10**USD_DECIMALS to do the same thing dynamically:
const USD_DECIMALS = 2;
const USD = 1 * 10**USD_DECIMALS;
// Or: const USD = 1 * Math.pow(10, USD_DECIMALS);
Live Example:
console.log("Various ways to get 10²:");
console.log(1e2);
const USD_DECIMALS = 2;
console.log(1 * Math.pow(10, USD_DECIMALS));
console.log(1 * 10**USD_DECIMALS);
console.log("Just for completeness, 10³:");
console.log(1e3);
const USD_DECIMALS3 = 3;
console.log(1 * Math.pow(10, USD_DECIMALS3));
console.log(1 * 10**USD_DECIMALS3);
.as-console-wrapper {
max-height: 100% !important;
}
(Side note: you sometimes need () around ** expressions where you may not expect to, such as in -1 ** 10, but not in the above.)
Just being a bit silly: you could add an e method to numbers. It's never a good idea to augment native prototypes in library code, but it can be okay in app-specific or page-specific code that doesn't have to integrate with unknown other code like libraries do, provided you do it correctly (make the extension non-enumerable). So FWIW:
Object.defineProperty(Number.prototype, "e", {
value(exp) {
return this * 10**exp;
},
// The usual set of flags for methods on built-in prototypes
// (`enumerable: false` is the default, but including it here
// just for emphasis)
writable: true,
configurable: true,
enumerable: false,
});
const USD_DECIMALS = 2;
console.log(1..e(USD_DECIMALS));
console.log((1).e(USD_DECIMALS));
let value = 1; // or whatever
console.log(value.e(USD_DECIMALS));
I probably wouldn't do it for this. Partially because I lean toward leaving native prototypes alone even in app-/page-specific code, and also because of the awkwardness of calling methods on numeric literals. Notice how I had to use 1..e(USD_DECIMALS) or (1).e(USD_DECIMALS) instead of just 1.e(USD_DECIMALS). That's because the . after a series of digits is part of the numeric literal, so it doesn't start a property/method access. The extra . solves that, or wrapping the literal in (). There's no problem when using a variable for the base value, since that's not a numeric literal, so value.e(USD_DECIMALS) works. So on the whole, for me, not worth it, but a bit of fun to look at.
The NeM is for the order of magnitude (N*10^M). What you can do is just
n=n*(10**m)
If you actually want to control the number of decimals you have to round.

How to display second zero when only single digit is returned after decimal, in JavaScript?

I have two functions here...
function getCostOne() {
var cost = 1.5;
return 1 * cost.toFixed(2);
}
and...
function getCostTwo() {
var cost = 1.5;
return 1 + cost.toFixed(2);
}
What is the difference between multiplying cost.toFixed(2) and adding cost.toFixed(2)?
Why does multiplying it return .5 and adding return .50?
Those functions return 1.5 and "11.50" respectively. Working JSBin Demo...
console.log(1 * '1.50');
console.log(1 + '1.50');
It looks like the string is cast in the first case (as though you had called parseFloat('1.50') and then concatted in the second. However, this is only the results on my own browser. Take a look at the official MDN Web Docs...
console.log('foo' * 2);
// expected output: NaN
So, Chrome is probably handling it well, but I wouldn't expect that kind of behavior across all browsers!
If you want them to both definitely return the right numbers, do all the mathematical logic first, and then format it with toFixed(). That code would look like...
function getCostTwo() {
var cost = 1.5;
cost += 1; // do the math logic FIRST!
return cost.toFixed(2); // once the number is just right, we format it!
}

Converting a website's price to a number with no decimals

I have a system that reads prices without decimals.
Example: 2890 = $28.90
I also have a system that takes a websites price of a product with the result being anywhere from $40.25 to just $40 (with no decimals places). I need most likely a regex or a function using javaScript or jQuery that would convert something like $40.25 to 4025 or $40 to 4000. Because I need to send the second system's returning number to the first system which will only except numbers without decimal places.
I originally thought I had it with this: item.price = Number(item.price.replace(/[^0-9\.-]+/g,"")*100); where item.price in this case equals $79.99 but I got a result back as 7998.99999999 instead of 7999 which is what I need and I can't have those decimals places, so parseFloat isn't an option. Would appreciate the help!
Don't re-invent the wheel, use a library! Try https://www.npmjs.com/package/parse-currency
import parseCurrency from 'parse-currency'
const foo = parseCurrency('$10.50')
console.log(foo) // 10.5
const bar = parseCurrency('$1,000,000.25')
console.log(bar) // 1000000.25
As Duncan mentioned, parse-currency library would be the way, but it is not enough for your problem. Let's make a better function...
function parseCurrency(amount) {
var number = amount.replace(/[^\d|\.]/g, ''); // Removes everything that's not a digit or a dot
var parsedToFloat = parseFloat(Math.round(number * 100) / 100); // Make a float number even it is an integer
return parsedToFloat.toFixed(2); // Now make sure that it will have always 2 decimal places
}
// This will return the following results...
parseCurrency('$40'); // "40.00"
parseCurrency('$40.25'); // "40.25"
parseCurrency('$40,000.25'); // "40000.25"
As you asked for a number that won't be fixed, you can do something like that:
const currencies = [
'$40',
'$45.25',
'$45.251123456789',
'$1,000',
'$1,000.25'
];
function convertToNumber(currency) {
const number = currency.replace(/[^\d|\.]/g, '');
return parseFloat(parseFloat(number).toFixed(2)) * 100;
}
console.log(currencies.map(convertToNumber))

Convert A Large Integer To a Hex String In Javascript

I need to find a way to convert a large number into a hex string in javascript. Straight off the bat, I tried myBigNumber.toString(16) but if myBigNumber has a very large value (eg 1298925419114529174706173) then myBigNumber.toString(16) will return an erroneous result, which is just brilliant. I tried writing by own function as follows:
function (integer) {
var result = '';
while (integer) {
result = (integer % 16).toString(16) + result;
integer = Math.floor(integer / 16);
}
}
However, large numbers modulo 16 all return 0 (I think this fundamental issue is what is causing the problem with toString. I also tried replacing (integer % 16) with (integer - 16 * Math.floor(integer/16)) but that had the same issue.
I have also looked at the Big Integer Javascript library but that is a huge plugin for one, hopefully relatively straightforward problem.
Any thoughts as to how I can get a valid result? Maybe some sort of divide and conquer approach? I am really rather stuck here.
Assuming you have your integer stored as a decimal string like '1298925419114529174706173':
function dec2hex(str){ // .toString(16) only works up to 2^53
var dec = str.toString().split(''), sum = [], hex = [], i, s
while(dec.length){
s = 1 * dec.shift()
for(i = 0; s || i < sum.length; i++){
s += (sum[i] || 0) * 10
sum[i] = s % 16
s = (s - sum[i]) / 16
}
}
while(sum.length){
hex.push(sum.pop().toString(16))
}
return hex.join('')
}
The numbers in question are above javascript's largest integer. However, you can work with such large numbers by strings and there are some plugins which can help you do this. An example which is particularly useful in this circumstance is hex2dec
The approach I took was to use the bignumber.js library and create a BigNumber passing in the value as a string then just use toString to convert to hex:
const BigNumber = require('bignumber.js');
const lrgIntStr = '1298925419114529174706173';
const bn = new BigNumber(lrgIntStr);
const hex = bn.toString(16);

Javascript Convert numbers to different formats or string alternative

UPDATED:
Using javascript or jQuery, how can I convert a number into it's different variations:
eg:
1000000
to...
1,000,000 or 1000K
OR
1000
to...
1,000 or 1K
OR
1934 and 1234
to...
1,934 or -2K (under 2000 but over 1500)
or
1,234 or 1k+ (over 1000 but under 1500)
Can this is done in a function?
Hope this make sense.
C
You can add methods to Number.prototype, so for example:
Number.prototype.addCommas = function () {
var intPart = Math.round(this).toString();
var decimalPart = (this - Math.round(this)).toString();
// Remove the "0." if it exists
if (decimalPart.length > 2) {
decimalPart = decimalPart.substring(2);
} else {
// Otherwise remove it altogether
decimalPart = '';
}
// Work through the digits three at a time
var i = intPart.length - 3;
while (i > 0) {
intPart = intPart.substring(0, i) + ',' + intPart.substring(i);
i = i - 3;
}
return intPart + decimalPart;
};
Now you can call this as var num = 1000; num.addCommas() and it will return "1,000". That's just an example, but you'll find that all the functions create will involve converting the numbers to strings early in the process then processing and returning the strings. (The separating integer and decimal part will probably be particularly useful so you might want to refactor that out into its own method.) Hopefully this is enough to get you started.
Edit: Here's how to do the K thing... this one's a bit simpler:
Number.prototype.k = function () {
// We don't want any thousands processing if the number is less than 1000.
if (this < 1000) {
// edit 2 May 2013: make sure it's a string for consistency
return this.toString();
}
// Round to 100s first so that we can get the decimal point in there
// then divide by 10 for thousands
var thousands = Math.round(this / 100) / 10;
// Now convert it to a string and add the k
return thousands.toString() + 'K';
};
Call this in the same way: var num = 2000; num.k()
Theoretically, yes.
As TimWolla points out, it requires a lot of logic.
Ruby on Rails have a helper for presenting time with words. Have a look at the documentation. The implementation for that code is found on GitHub, and could give you some hint as how to go about implementing this.
I agree with the comment to reduce the complexity by choosing one format.
Hope you find some help in my answer.

Categories