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))
Related
I just started learning js and so far am making good progress. I have encountered an issue tho, and the title should basically tell you everything you need to know, but here goes anyways.
For the project I want to realize eventually, I'll need rather big numbers. So I came up with the following to format them to scientific notation:
<script>
var rawNumber = 172 ** 25; // The number that shall be formatted into scientific notation
var exponentDisplay = "e+"; // Self explainatory
var numberRelevantDigits = 0; // The digits displayed before the "e+"
var numberExponent = 0; // Self explainatory
var formattedNumberDisplay = 0; // What will be displayed
function formatNumber() { // The function triggered by clicking the button
var numberExponent = Math.floor( Math.log(rawNumber) / Math.log(10) ); // Calculating the exponent of the number in scientific notation
var numberRelevantDigits = rawNumber / 10 ** numberExponent; // Dividing the number by 10 to the power of its exponent
var numberRelevantDigits = numberRelevantDigits.toFixed(3); // Rounds the relevant digits to 3 decimals
var formattedNumberDisplay = numberRelevantDigits + exponentDisplay + numberExponent; // Adding the relevant digits, "e+" and the exponent into a string
document.getElementById("formattedNumberDisplay").innerHTML = formattedNumberDisplay; // Changing the display to the formatted number
}
</script>
This works as intended, but I don't want to put this chunk of code whenever I need a number formatted. Is there a way (or rather: which is the way) to make it so I can just call that function whenever I need a number formatted? Even if I need use different variables?
Let me apologize again, since this has likely been answered a dozen times before, but I don't even have a clue what to even look for.
Thank y'all in advance.
Create a js file and import it whenever you want
also you should pass the variables to the functions instead of declaring them as a var
inside funciton use const and let, you might some ugly bugs in the future if you don't.
Your file NumberFormater.js will look like:
export formatNumber = (
rawNumber,
exponentDisplay,
numberRelevantDigits,
numberExponent,
formattedNumberDisplay
) => {
let numberExponent = Math.floor( Math.log(rawNumber) / Math.log(10) ); // Calculating the exponent of the number in scientific notation
let numberRelevantDigits = rawNumber / 10 ** numberExponent; // Dividing the number by 10 to the power of its exponent
let numberRelevantDigits = numberRelevantDigits.toFixed(3); // Rounds the relevant digits to 3 decimals
let formattedNumberDisplay = numberRelevantDigits + exponentDisplay + numberExponent; // Adding the relevant digits, "e+" and the exponent into a string
document.getElementById("formattedNumberDisplay").innerHTML = formattedNumberDisplay; // Changing the display to the formatted number
}
then when needed:
import { formatNumber } from './NumberFormater.js';
const rawNumber = 172 ** 25; // The number that shall be formatted into scientific notation
const exponentDisplay = "e+"; // Self explainatory
const numberRelevantDigits = 0; // The digits displayed before the "e+"
const numberExponent = 0; // Self explainatory
const formattedNumberDisplay = 0; // What will be displayed
formatNumber( rawNumber, exponentDisplay, numberRelevantDigits, numberExponent, formattedNumberDisplay);
read more on js modules https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
Hope I've helped.
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).
If the value of f5 cell in a Google Sheet is 1.1000 (a number formatted to 4 decimal places) and the value of f6 is = f5 * 1.073, how can I ensure I get the same result multiplying those values in Javascript, eg:
var original_value = 1.1000;
var derivative_value = original_value * 1.073;
Specifically, my question is - will the result of the Javascript multiplication (derivative_value) be the same as the result of the Google formula (f6)? And if not, how can I make it so that it is?
Context / What I've Tried
For context, this question is part of a larger question I am trying to resolve for which I have set up this JSFiddle.
The JSFiddle has an input for the original_value and an input for the multiplier.
It outputs the result to four decimal places and adds trailing zeros where required (this is the required format for the result).
It is an attempt to check that the Javascript code I am writing will produce the same result as the Google Sheet formula.
[ The JSFiddle has been updated to also log decimal.js results to the console for comparison ]
Edit
There was a suggestion to use decimal.js but I'm not sure how it would be applied - something like the following?
var original_value = new Decimal(1.1000);
// some different multipliers for testing
var multiplier_a = new Decimal(1.073);
var multiplier_b = new Decimal(1.1);
// some different results for testing
var derivative_value_a = original_value.times(multiplier_a).toString();
var derivative_value_b = original_value.times(multiplier_b).toString();
console.log(derivative_value_a); // 1.1803
console.log(derivative_value_b); // 1.21
Is that any more accurate than plain Javascript original_value * multiplier? More importantly for this question, will it always simulate the same result that a Google Sheet formula produces?
JavaScript is using so called double precision float format (64 bit)- https://tc39.github.io/ecma262/#sec-terms-and-definitions-number-value
Google Sheets seem to use the same format, you can test it by =f6*1E13 - round(f6*1E13) to see that f6 is not STORED as a fixed number format, only FORMATTED
see Number.toFixed how to FORMAT numbers in Javascript
to generate some test data:
[...Array(10)].forEach(() => {
const f5 = 1.1
const x = Math.random() / 100
const f6 = f5 * x
console.log(x, f6.toFixed(4))
})
and compare in Google Sheet:
https://docs.google.com/spreadsheets/d/1jKBwzM41nwIEyatLUHEUwteK8ImJg334hzJ8nKkUZ5M/view
=> all rounded numbers are equal.
P.S.: you need to copy the console output, paste into the Sheet, use the menu item Data > Split text into columns... > Space, then multiply by 1.1 in 3rd column and finally format all numbers
After revisiting this I have updated the jsFiddle.
The main components of what I believe are a satisfactory solution are:
Convert both original_value and multiplier to decimal.js objects.
Do the multiplication using the decimal.js times method.
Do the rounding using the decimal.js toDecimalPlaces method.
Use the argument values (4,7) to define 4 decimal places with ROUND_HALF_CEIL rounding, equivalent to Math.round (reference)
For example:
var my_decimal_js_value = new Decimal(original_value).times(new Decimal(multiplier)).toDecimalPlaces(4, 7);
In order to add any necessary trailing zeros to the result, I use:
function trailingZeros(my_decimal_js_value) {
var result = my_decimal_js_value;
// add zeros if required:
var split_result = result.toString().split(".");
// if there are decimals present
if (split_result[1] != undefined) {
// declare trailing_zeros;
var trailing_zeros;
// get the amount of decimal numbers
decimals_present = split_result[1].length;
// if one decimal number, add three trailing zeros
if (decimals_present === 1) {
trailing_zeros = "000";
result += trailing_zeros;
}
// if two decimal numbers, add two trailing zeros
else if (decimals_present === 2) {
trailing_zeros = "00";
result += trailing_zeros;
}
// if three decimal numbers, add one trailing zero
else if (decimals_present === 3) {
trailing_zeros = "0";
result += trailing_zeros;
}
// if four decimal numbers, just convert result to string
else if (decimals_present === 4) {
result = result.toString();
}
}
// if there are no decimals present, add a decimal place and four zeros
else if (split_result[1] === undefined) {
trailing_zeros = ".0000";
result += trailing_zeros;
}
return result;
}
I am still not absolutely certain that this mimics the Google Sheet multiplication formula, however using decimal.js, or another dedicated decimal library, seems to be the preferred method over plain JavaScript (to avoid possible rounding errors), based on posts such as these:
http://www.jacklmoore.com/notes/rounding-in-javascript
Is floating point math broken?
https://spin.atomicobject.com/2016/01/04/javascript-math-precision-decimals
Using JS to run a simple formula, but like many JS calculations I've made before the decimal answers go on for way longer than I'd like and make it look sloppy.
Is there I way I can force the calculation to stop at a certain decimal place or force a round up from there?
Thanks!
<script>
var $u = $('input[name=u]');
var $a = $('input[name=a]');
var $h = $('input[name=h]');
$u.on('keyup',function() {
var u = +$u.val();
var a = +$a.val();
$h.val(u*4.605+a*1.308+28.003).toFixed(1);
});
$a.on('keyup',function() {
var u = +$u.val();
var a = +$a.val();
$h.val(u*4.605+a*1.308+28.003).toFixed(1);
});
</script>
I see you've tried toFixed(). I believe that is the solution, but you're trying to call it on a jQuery object. You should call it on the number before passing it into val().
Change your code to:
$a.on('keyup',function() {
var u = +$u.val();
var a = +$a.val();
$h.val((u*4.605+a*1.308+28.003).toFixed(1));
});
// $('#a').val(Math.PI).toFixed(1); // You're inserting the full value, and then executing
// toFixed on a jQuery Object. Not going to work.
$('#a').val( (Math.PI).toFixed(1) ); // How it should be written
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input id="a"/>
Math.floor(number)
Returns the next integer below given number.
Math.floor(1.66); // 1
Math.floor(-1.66); // -2
Math.ceil(number)
Returns the next integer above given number.
Math.ceil(1.66); // 2
Math.ceil(-1.66); // -1
Math.round(number)
Returns the nearest integer. Similar to Math.floor(number + 0.5);
Math.round(1.66); // 2
Math.round(-1.66); // -2
number|0 (or ~~number)
Discards the decimal portion of a number.
1.66|0; // 1
-1.66|0; // -1
number.toFixed(decimals)
Converts a number into a string with the specified number of decimals. Will either pad the result with zeroes or mathematically round to a certain number of decimals.
(1.66).toFixed(1); // "1.7"
(-1.66).toFixed(1); // "-1.7"
number.toFixed(decimals + 1).slice(0, -1)
Returns a fixed-decimal string, but chops the specified number of decimals without rounding.
(1.66).toFixed(2).slice(0, -1); // "1.6"
I have a product to add into the store, where there are two input fields priceBase and priceFinal. First is without TAX, second is with TAX.
While using this javascript function:
jQuery(function($){
var priceBase = $('input[name="mprices[basePrice][]"]', '#productPriceBody');
var priceFinal = $('input[name="mprices[salesPrice][]"]', '#productPriceBody');
var priceDiff = priceFinal.val() - priceBase.val();
var priceTax = priceDiff / priceBase.val();
alert(priceFinal.val()); // 1.40004
alert(priceBase.val()); // 1.16667
alert(priceDiff); // 0.23333399999999993
alert(priceTax); // 0.19999999999999993
});
How I suppose to round a priceTax value from 0.19999999999999993 to 0.20 ? Like normal math calculation you know, if it's 4 and below, it rounds to lower, if it's 5 it rounds to higher number.
Thanks for suggestions in advance.
You seem to want
alert(priceDiff.toFixed(2));
But you should parse the values before you do maths. It works here because you're lucky :
"33"-"12" => "21"
"33"+"12" => "3312"
So to avoid bugs in the future (when you use + instead of - for example) I'd suggest to always parse the field values :
var priceDiff = parseFloat(priceFinal.val()) - parseFloat(priceBase.val());