Truncate decimal number (as strings) to a fixed number of places - javascript

I want to truncate numbers (given as strings) to a fixed number of decimal places. The numbers can be negative (with a minus sign), positive (no sign). I'd prefer to round the numbers properly and keep trailing zeroes. I want the same number of decimal places, no matter how long the whole number is. The numbers will be stored back as strings.
For example:
140.234234234 -> 140.234
1.123123 -> 1.123
-12.789789 -> -12.790

First parse them as floats, then format with toFixed:
var nums = [
"140.234234234", // -> 140.234
"1.123123", // -> 1.123
"-12.789789" // -> -12.790
];
nums.forEach(function(n) {
console.log(parseFloat(n).toFixed(3));
});
http://codepen.io/anon/pen/IvxmA

Any number can be displayed as a fixed decimal place string by using .toFixed:
var num = 140.234234234;
var fixedDecimalPlace = num.toFixed(3); // is "140.234"

function truncate( numberString, trunk ) {
var onpoint = numberString.split('.',2);
var numberStringTruncated = numberString;
if (onpoint.length > 1) {
numberStringTruncated = onpoint[0] + '.' + onpoint[1].substring(0,trunk);
}
return numberStringTruncated;
}
This does not consider rounding or padding. As the other answer suggested, you should use parseFloat followed by toFixed

Related

Multiply points of a string

Let's say that I have a list of points declared in this format: x1,y1 x2,y2
listOfPoints : string = "12.2, 13.0 198.2, 141";
What could I do to multiply by 1.5, for example, every number of this string ?
Do I need to iterate over the listOfPoints and extract a string every time that there is a ', ' or ' ', convert that string into a number, multiply it by 1.5 and reconvert it into a string to finally put it into a new string (newListOfPoints) ?
Or is there a different way to that more efficiently ?
Thank you.
Use a regular expression with a replacer function to match digits, possibly with decimals, and replace with those digits multiplied by the number you want:
const listOfPoints = "12.2, 13.0 198.2, 141";
const multiplied = listOfPoints.replace(
/\d+(?:\.\d+)?/g,
match => match * 1.5
);
console.log(multiplied);
Due to floating-point issues, some of the resulting numbers may have trailing digits. If you don't want that, you can round the multiplied number to a certain number of decimal places:
const listOfPoints = "12.2, 13.0 198.2, 141";
const multiplied = listOfPoints.replace(
/\d+(?:\.\d+)?/g,
match => Math.round(1000 * match * 1.5) / 1000
);
console.log(multiplied);

Javascript: how to get micronumbers in decimal format

I have simple function that calculates number of decimals,
eg. _d(0.01) = 2, _d(0.001) = 3 and so on.
We added some new coins to our system that have 0.00000001 quantity and function broke.
Here is why:
0.00000001.toString() = 1e-8, so I cant split it it by '.' and calculate length of second part as I did before.
So the question is - how to get string '0.00000001' out of 0.00000001 number easiest way.
EDIT
I didnt mean exactly '0.00000001', I meant any micronumber to decimal without exp. Some function _d(x) that would work _d(0.000000000012) = '0.000000000012'and so on. What usually toString() does to large (but not too large) numbers.
Use toFixed() with a large number of digits, then count the number of zeroes after the decimal point.
function _d(num) {
var str = num.toFixed(100);
var fraction = str.split('.')[1];
var zeros = fraction.match(/^0*/)[0].length;
return zeros + 1;
}
console.log(_d(0.1));
console.log(_d(0.01));
console.log(_d(0.000000001));
Do you want some thing like this
function decimalPlaces(num) {
var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match) { return 0; }
return Math.max(
0,
// Number of digits right of decimal point.
(match[1] ? match[1].length : 0)
// Adjust for scientific notation.
- (match[2] ? +match[2] : 0));
}
console.log(decimalPlaces(0.000000001))
First off, I got some inspiration for this answer from here:
How to avoid scientific notation for large numbers in JavaScript?
You can convert the number to a strong and then check for str.indexOf("e"). If true, then just return the scientific notation part of the string. For example:
function _d() {
// your current function here
if (str.indexOf("e")) {
var something = str.split("-")[1];
return something;
}
}
EDIT: I was working on this before your last comment to me, so this returns a string of the number, which I thought was what you wanted.
Leaving aside the point about significant digits, which is meaningful and correct but does not solve your problem, try this. We take the number, convert to string, if that string is not scientific notation then the answer is trivial. If it is scientific notation, then split the string twice (once on "e-" and then split the zeroth array on "." Add str[1]-1 zeroes to the lead of the number and add the digits to the end.
function _d(arg) {
var str = arg.toString();
if (str.indexOf("e-")) {
var digits = str.split("e-")[0];
var zeroes = str.split("e-")[1];
var zero = Number(zeroes);
var each = digits.split(".");
var something = "0.";
for (var i = 0; i < zeroes-1; i++) {
something += "0";
}
for (var j = 0; j < each.length; j++) {
something = something + each[j];
}
return something;
}
}
This won't work with very large numbers or very small negative numbers. And its pretty convoluted.
The other way is to use .toString() and then look for .length-2(2 characters - '0.'. It should give you the number of zeros.
The advantage of this method is you don't need to know the number of maximum decimals in the number.
To keep it as the full decimal:
Number(0.000001)
// 0.000001
To show it as a string:
0.000001.toFixed(6)
// "0.000001"

Parsing toLocaleString and back to float loosing precision

This is what works as expected:
This parseFloat(newValue).toLocaleString("de-DE", { minimumFractionDigits: 2, maximumFractionDigits: 2 }) will result in a String: "34.886,55"
This does not work as expected:
For parseFloat("34.886,55") I get a Number, but I lost everything after the comma: 34.886.
How can I fix this problem ?
I wrote this simple function for doing locale based parseFloat, to the best of my knowledge, the assumptions for this function are.
The decimal operator will come once.
So split it at the decimal("," in our case) to get two elements in an array.
Then remove the thousands separator("." in our case) for each of the elements in the array.
Then joinback the array with the decimal separator ("." in our case)
finally return the parseFloat value of this joined number!
var str = "34.886,55"
console.log("before: ", str);
str = localeParseFloat(str, ",", ".");
console.log("resulting floating value from the function: ", str);
function localeParseFloat(str, decimalChar, separatorChar){
var out = [];
str.split(",").map(function(x){
x = x.replace(".", "");
out.push(x);
})
out = out.join(".");
return parseFloat(out);
}
<script src="https://rawgit.com/eu81273/jsfiddle-console/master/console.js"></script>
Here's a brief example of the number parsing... Commas are not valid in numbers, only the full stop represents the decimal separator. If it is encountered, the string conversion stop, as you can see on the second log. Also check the third log, I've added a check for the value to be true if it's lower than 100, making it more obvious that you are not playing with thousand separator but really decimal separator.
console.log(parseFloat("34.886.55"));
console.log(parseFloat("34,886.55"));
console.log(parseFloat("34.886,55"), parseFloat("34.886,55") < 100);

parseInt() doesn't regard leading zeros, even with radix

When I want to convert a binary string to a base 10 decimal (Like this: parseInt('0001010', 2)), Javascript returns a decimal number, but a version in which the leading zeros mentioned in the example above have been disregarded. Is there any way to fix this?
So supposing you have the number '00000101101101':
var number = '00000101101101';
var length = number.length;
var decimal_number = parseInt(number, 2);
// going back
var new_number = decimal_number.toString(2);
var new_length = new_number.length;
var n_zeros = length - new_length;
var zeros = (n_zeros >= 2 ? Array(n_zeros+1).join("0") : "0");
new_number = zeros + new_number;
The decimal representation has no way to keep track of leading zeros. If you wish to keep the leading zeros in the result, you need a fundamentally different approach (e.g. keeping the output as a string).
Alternatively, if you know the width of the result a priori, you could just pad it with leading zeros on output.

Javascript: Convert a string representation of money to Number

Lets say I have an amount in string format like this:
amount = '12,000.00'
I want to convert it into a Number (Javascript) or a float.
parseFloat(amount) // this gives me 12 as a result
Number(amount) // this gives me NaN as a result
Other solution I thought was this:
parseFloat(amount.replace(/[,]/g, ''))
This works fine. But the problem here is the Locale.
This would fail when the amount is € 12000,00.
Here ',' has altogether a different meaning.
I looked around for a good solution but couldn't. I am looking for a generalized solution.
This is not that easy, as you can't exactly know what's the delimiter for thousands and what for the decimal part
Consider "12.000.000" is it 12000.000 === 12000 or 12000000?
But if you would set the requirement that the last delimiter is always the decimal delimiter -
meaning if at least one delimiter is given, the last one has to be the decimal delimiter, *if the digits following, don't exceed a defined length.
Then you could try the following
Edit
(see the revs if you're interested in the old function)
I put in the ability to define the max length of digits after the last delimiter "," or "." up until it is treated as float, after that its returned as integer
var amounts = ["12000","12.000,00", "12,000.00", "12,000,01", "12.000.02", "12,000,001"];
formatMoney.maxDecLength = 3; //Set to Infinity o.s. to disable it
function formatMoney(a) {
var nums = a.split(/[,\.]/);
var ret = [nums.slice(0, nums.length - 1).join("")];
if (nums.length < 2) return +nums[0];
ret.push(nums[nums.length - 1]);
return +(ret.join(nums[nums.length - 1].length < formatMoney.maxDecLength ? "." : ""));
}
for ( var i=0,j;j=amounts[i];i++)
console.log (j + " -> " +formatMoney(j));
Gives the output:
"12000 -> 12000"
"12.000,00 -> 12000"
"12,000.00 -> 12000"
"12,000,01 -> 12000.01"
"12.000.02 -> 12000.02"
"12,000,001 -> 12000001" //as you can see after the last "," there are 3 digits and its treated as integer
Another JSBin
You can get the local decimal delimiter in this manner:
1.1.toLocaleString().substr(1,1)
Before parse float, you could make sure the string contains nothing but numbers, possibly a minus sign, and the local decimal delimiter.
The truth is, you'll never know the format. 12,345. Is that 12345, or another locale version if 12.345?
However, if you have consistent decimals, then you'd be able to use the lastIndexOf function on a comma and a period will reveal the decimal position and character.
var price = '12,345.67';
var lastPeriod = price.lastIndexOf('.');
var lastComma = price.lastIndexOf(',');
if (lastComma != -1 && lastComma > lastPeriod) {
decimalCharacter = ',';
} else {
decimalCharacter = '.';
}
console.log(decimalCharacter); //. or , based on how the price string looks - see below
If price is 12,345.67, decimalCharacter will be .. If it's 12.345,67, it'll be returned as ,.

Categories

Resources