Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 11 days ago.
The community reviewed whether to reopen this question 11 days ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have written an application in Javascript (NodeJS) which returns strings like the following.
"£20,000"
I am relatively new to Javascript, and I don't recall having worked on any applications in the past in other languages where I had to parse strings containing prices or currencies.
Consequently I am lost and have no idea how to deal with this.
What I want to do is two things:
Obtain the numerical value (20000)
Obtain an ISO code corresponding to the currency ("GBP")
If the string is invalid format then this should be treated as an error case. (eg: Exception raised.)
How do I convert the string "£20,000" to an object containing two components - the ISO code and the numerical value, throwing an exception in the case of an invalidly formatted input.
I did some research and found three libraries which claim to be useful for dealing with "money types" in Javascript, however none of these solve my problem.
https://currency.js.org/
http://openexchangerates.github.io/accounting.js/
http://openexchangerates.github.io/money.js/
The latter appears to be a library for performing FX conversions which isn't what I am looking for.
Currency.js appears to be able to produce currency strings, and perform math functions with currency values, but it doesn't appear to be able to parse a currency or price string.
Accounting.js appears to have something close: unformat (alias parse) functions. However these appear to just strip out currency symbols from a string leaving the value. This is only part of what I need.
Here is a solution using a regex and an ISO currency code lookup:
const isoLookup = {
'CHF': 'CHF',
'CH': 'CHF',
'EUR': 'EUR',
'€': 'EUR',
'GBP': 'GBP',
'£': 'GBP',
'USD': 'USD',
'$': 'USD',
'US$': 'USD',
'JPY': 'JPY',
'Y': 'JPY',
'¥': 'JPY',
};
function convertCurrency(str) {
const regex = /^\s*([^\s\d]+)\s*(-?[\d,.]+)\s*$/;
let m = str.match(regex);
let result = null;
if(m && isoLookup[m[1]]) {
result = {
currency: isoLookup[m[1]],
value: Number(m[2].replace(/,/g, ''))
}
} // else throw error if desired
return result;
}
[
'GBP 20,000',
'£20,000',
'£ 20,000',
'$123,567.89',
'USD12.34',
'US$12.34',
'US$ 12.34',
'€100',
'CH 100',
'XY 999',
'# 999'
].forEach(str => {
let result = convertCurrency(str);
console.log(str, '==>', JSON.stringify(result));
});
Output:
GBP 20,000 ==> {"currency":"GBP","value":20000}
£20,000 ==> {"currency":"GBP","value":20000}
£ 20,000 ==> {"currency":"GBP","value":20000}
$123,567.89 ==> {"currency":"USD","value":123567.89}
USD12.34 ==> {"currency":"USD","value":12.34}
US$12.34 ==> {"currency":"USD","value":12.34}
US$ 12.34 ==> {"currency":"USD","value":12.34}
€100 ==> {"currency":"EUR","value":100}
CH 100 ==> {"currency":"CHF","value":100}
XY 999 ==> null
# 999 ==> null
Notes:
the regex splits the currency and value, and allows optional spaces before, in between, and after
the ISO currency code is looked up with the isoLookup object. Expand as needed, see https://www.iban.com/currency-codes
the value string is converted to a number after removing ,. Keep in mind that most locales use format 12,345.00, where a few use 12.345,00. Another regex is needed to support the latter.
a null is returned if an invalid format or unknown currency is encountered; you can throw an error if desired
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 10 months ago.
Improve this question
I have a task to filter out a number which is bigger than 9e+65 (65 zeros).
As input I have a number and as output I need to return a boolean value. The function can accept regular formatted numbers (42342) and any scientific notation (1e5).
My approach is:
const 65zerosCheck = (num: number):boolean =>
num.toString().includes("e+")
: Number(value.toString().split('e+')[1]) > 65
: false
It looks dirty and the reviewer didn't accept it.
To quote MDN:
In JavaScript, numbers are implemented in double-precision 64-bit binary format IEEE 754 (i.e., a number between ±2^−1022 and ±2^+1023, or about ±10^−308 to ±10^+308, with a numeric precision of 53 bits). Integer values up to ±2^53 − 1 can be represented exactly.
You do not have to worry about such huge numbers. I have added a link to MDN quote above at the end of this snippet where it is discussed in details about how Javascript handles Numbers.
const HUGE_NUMBER_THRESHOLD = 9e+65;
const checkHugeNumbers = (num) => num > HUGE_NUMBER_THRESHOLD;
let myTestNum = 9000000000000000000000000000000000000000000000000000000000000000000;
console.log(checkHugeNumbers(myTestNum));
// OUTPUT:
// true
For further study, here is the reference link.
There doesn't seem to be anything logically wrong with your approach, but if your reviewer is asking for a cleaner approach, this is my suggestion.
It does the same thing, but is more readable and its easy to add on to, in the future. Splitting up the logic and results into descriptive variables makes it easier to read, and catch any errors or oversights that may be encountered.
Also you can save a step by directly getting the index, without using split and creating three types (array, string, and number), that can make it confusing to follow. This approach keeps everything between strings and numbers
const checkOver65Zeros = (num: number) =>{
const numString = num.toString()
const idxOfZeros = numString.indexOf("e+")
if(idxOfZeros!== -1)
return Number(numString.substring(idxOfZeros + 2)) > 65
return false
}
console.log(checkOver65Zeros(900000000000000000000000000000000000000))
This question already has answers here:
Replacing only a part of regexp matching
(4 answers)
Closed 1 year ago.
I am attempting to correct a grammar error from an API. I'm attempting to replace 70,2bn to 70.2bn I've went about it to just simply to .replace(/,[0-9]bn/g, '.') but this ends up removing the last number after the comma.
Here is an example of the full string "The average population is 492,213 and revenue generated is 70,2bn"
With the current .replace(/,[0-9]bn/g, '.') it is replacing the comma with a period which I am expecting, but how can I return back the number that is cut off?
This number 70,2bn is different per page, so I attempting to find a solution that will work for different scenarios that include bn such as 2,1bn, 100,3bn etc.
Here is a code snippet:
let string = "The average population is 492,213 and revenue generated is 70,2bn"
console.log(string)
string = string.replace(/,[0-9]bn/g, '.bn')
console.log(string)
I am expecting an outcome of "The average population is 492,213 and revenue generated is 70.2bn"
Try this:
> '70,2bn'.replace(/(\d+),(\d+bn\b)/g, '$1.$2')
"70.2bn"
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
How to get all number from beginning of string until first non-number?
For example, I want to get 12345 from '12345abc' and another example get 5678 from '5678kkk'.
Is any way can do this?
You could use RegExp#match with ^ anchor, to find out the numeric characters from beginning:
const string = "12345abc";
const matches = string.match(/^\d+/);
// Fallback if no matches found
const numbers = (matches || [])[0];
console.log(numbers);
Use parseInt() as it will stripe out all the characters other than the numeric character so you do not need custom logic for getting the numeric value as you have described:
console.log(parseInt('12345abc'));
The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).
Use parseInt
let str = '5678kkk';
console.log(parseInt(str));
I have to display a number in currency format using the country code with comma and period separators based on the country.
Example if the number is 4294967295000 then
USA = USD 4,294,967,295,000.00
INDIA = INR 42,94,96,72,95,000.00
I got it working for India, but for USA I am getting this string but I need space between currency code and number:
var number = 4294967295000;
console.log(number.toLocaleString('en-IN', {
style: 'currency', currency: 'INR', currencyDisplay: 'code'
})); // INR 42,94,96,72,95,000.00
console.log(number.toLocaleString('en-US', {
style: 'currency', currency: 'USD', currencyDisplay: 'code'
})); // USD4,294,967,295,000.00
How do I achieve spacing between "USD" and number? I did not see anyting in option parameter regarding space. I can write custom code to add space, but I am trying to see if there is better option for doing the same.
I did not see anyting in option parameter regarding space.
So I set off down the rabbit hole.
When you pass options in to toLocaleString, it follows a number of steps. Firstly, it converts your passed in options to a NumberFormat object. It goes through a series of steps to do so, one of which is:
If s is "currency", then
a. Let c be converting c to upper case as specified in 6.1.
b. Set numberFormat.[[currency]] to c.
That means that whatever you've passed in as the currency option, so long as it's a proper currency code, is converted to uppercase and stored in the internal currency property on the NumberFormat object.
We then see that there are some other internal properties used on a NumberFormat - in this case, specifically the positivePattern internal slot. The spec notes:
The value of these properties must be string values that contain a substring "{number}"; the values within the currency property must also contain a substring "{currency}". The pattern strings must not contain any characters in the General Category “Number, decimal digit" as specified by the Unicode Standard.
IE note that at this point, for a given culture, we've created an object that effectively has a formatting string along the lines of {currency} {number}. Only in Chrome's (at least) case for USD, it is {currency}{number}. Note that in IE and Edge, you get the space after USD, so it's decided on a formatting string of {currency} {number}.
Next up, we get to the actual implementation of formatting the number. Step 7 says:
If the value of the numberFormat.[[style]] is "currency", then
a. Let currency be the value of numberFormat.[[currency]].
b. If numberFormat.[[currencyDisplay]] is "code", then
i. Let cd be currency.
c. Else, if numberFormat.[[currencyDisplay]] is "symbol", then
i. Let cd be an ILD string representing currency in short form. If the implementation does not have such a representation of currency, then use currency itself.
d. Else, if numberFormat.[[currencyDisplay]] is "name", then
i. Let cd be an ILD string representing currency in long form. If the implementation does not have such a representation of currency, then use currency itself.
e. Replace the substring "{currency}" within result with cd.
emphasis mine, showing the steps taken in this case.
TL;DR - this behaviour appears to browser dependent, and you'll need to parse and fix the resulting string yourself if you consistently want the space, there's no built-in way to do so.
If it's a reliable pattern that what you want to fix is a three-letter code followed by a digit, and you want to fix that by inserting a space, you could use this regex like this:
currencyStr = currencyStr.replace(/^([A-Z]{3})(\d)/, (match, $1, $2) => $1 + ' ' + $2);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
As you can see from the title I have various cases for strings that can contain numbers in them. I found out that using parseInt() and parseFloat() didn't work for me as parseInt will convert number like 10.28 to just 10, but parseFloat will make number like 10 into 10.0, I want to somehow convert string into number so it stays exactly like it was in the string without anything removed or added.
Per MDN Number ( MSDN page also, but not so much info ).
At the top of the page:
The primary uses for the Number object are:
If the argument cannot be converted into a number, it returns NaN.
In a non-constructor context (i.e., without the new operator), Number can be used to perform a type conversion.
At the bottom of the page, there are some examples:
Convert numeric strings to numbers
Number("123") // 123
Number("") // 0
Number("0x11") // 17
Number("0b11") // 3
Number("0o11") // 9
Number("foo") // NaN
Number("100a") // NaN
Demo https://jsfiddle.net/hxkfafdw/
More on the topic - Number("foo") is NaN Number("f00") - same. Number("0xf000") - this is a hex number.