Javascript: How to retrieve the number of decimals of a *string* number? - javascript

I have a set of string numbers having decimals, for example: 23.456, 9.450, 123.01... I need to retrieve the number of decimals for each number, knowing that they have at least 1 decimal.
In other words, the retr_dec() method should return the following:
retr_dec("23.456") -> 3
retr_dec("9.450") -> 3
retr_dec("123.01") -> 2
Trailing zeros do count as a decimal in this case, unlike in this related question.
Is there an easy/delivered method to achieve this in Javascript or should I compute the decimal point position and compute the difference with the string length? Thanks

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));
}
The extra complexity is to handle scientific notation so
decimalPlaces('.05')
2
decimalPlaces('.5')
1
decimalPlaces('1')
0
decimalPlaces('25e-100')
100
decimalPlaces('2.5e-99')
100
decimalPlaces('.5e1')
0
decimalPlaces('.25e1')
1

function retr_dec(num) {
return (num.split('.')[1] || []).length;
}

function retr_dec(numStr) {
var pieces = numStr.split(".");
return pieces[1].length;
}

Since there is not already a regex-based answer:
/\d*$/.exec(strNum)[0].length
Note that this "fails" for integers, but per the problem specification they will never occur.

You could get the length of the decimal part of your number this way:
var value = 192.123123;
stringValue = value.toString();
length = stringValue.split('.')[1].length;
It makes the number a string, splits the string in two (at the decimal point) and returns the length of the second element of the array returned by the split operation and stores it in the 'length' variable.

Try using String.prototype.match() with RegExp /\..*/ , return .length of matched string -1
function retr_decs(args) {
return /\./.test(args) && args.match(/\..*/)[0].length - 1 || "no decimal found"
}
console.log(
retr_decs("23.456") // 3
, retr_decs("9.450") // 3
, retr_decs("123.01") // 2
, retr_decs("123") // "no decimal found"
)

I had to deal with very small numbers so I created a version that can handle numbers like 1e-7.
Number.prototype.getPrecision = function() {
var v = this.valueOf();
if (Math.floor(v) === v) return 0;
var str = this.toString();
var ep = str.split("e-");
if (ep.length > 1) {
var np = Number(ep[0]);
return np.getPrecision() + Number(ep[1]);
}
var dp = str.split(".");
if (dp.length > 1) {
return dp[1].length;
}
return 0;
}
document.write("NaN => " + Number("NaN").getPrecision() + "<br>");
document.write("void => " + Number("").getPrecision() + "<br>");
document.write("12.1234 => " + Number("12.1234").getPrecision() + "<br>");
document.write("1212 => " + Number("1212").getPrecision() + "<br>");
document.write("0.0000001 => " + Number("0.0000001").getPrecision() + "<br>");
document.write("1.12e-23 => " + Number("1.12e-23").getPrecision() + "<br>");
document.write("1.12e8 => " + Number("1.12e8").getPrecision() + "<br>");

A slight modification of the currently accepted answer, this adds to the Number prototype, thereby allowing all number variables to execute this method:
if (!Number.prototype.getDecimals) {
Number.prototype.getDecimals = function() {
var num = this,
match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match)
return 0;
return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
}
}
It can be used like so:
// Get a number's decimals.
var number = 1.235256;
console.debug(number + " has " + number.getDecimals() + " decimal places.");
// Get a number string's decimals.
var number = "634.2384023";
console.debug(number + " has " + parseFloat(number).getDecimals() + " decimal places.");
Utilizing our existing code, the second case could also be easily added to the String prototype like so:
if (!String.prototype.getDecimals) {
String.prototype.getDecimals = function() {
return parseFloat(this).getDecimals();
}
}
Use this like:
console.debug("45.2342".getDecimals());

A bit of a hybrid of two others on here but this worked for me. Outside cases in my code weren't handled by others here. However, I had removed the scientific decimal place counter. Which I would have loved at uni!
numberOfDecimalPlaces: function (number) {
var match = ('' + number).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match || match[0] == 0) {
return 0;
}
return match[0].length;
}

Based on Liam Middleton's answer, here's what I did (without scientific notation):
numberOfDecimalPlaces = (number) => {
let match = (number + "").match(/(?:\.(\d+))?$/);
if (!match || !match[1]) {
return 0;
}
return match[1].length;
};
alert(numberOfDecimalPlaces(42.21));

function decimalPlaces(n) {
if (n === NaN || n === Infinity)
return 0;
n = ('' + n).split('.');
if (n.length == 1) {
if (Boolean(n[0].match(/e/g)))
return ~~(n[0].split('e-'))[1];
return 0;
}
n = n[1].split('e-');
return n[0].length + ~~n[1];
}

Related

Adding two numbers JS

I want to add two numbers from range 10-99,for example:
Input:16
Output:1+6=7
Input:99
Output:18
function digital_root(n) {
var z = n.toString().length;
if (z == 2) {
var x = z[0] + z[1]
return x;
}
}
console.log( digital_root(16) );
Output from this code is NaN.What should I correct?
You can try this:
function digital_root(n) {
var z = n.toString();
//use length here
if (z.length == 2) {
//convert to int
var x = parseInt(z[0]) + parseInt(z[1]);
return x;
} else {
return "not possible!";
}
}
console.log( digital_root(16) );
console.log( digital_root(99) );
console.log( digital_root(999) );
Use split to split the string in half and add the two using parseInt to convert to a number.
const sum = (s) => (''+s).split('').reduce((a,b) => parseInt(a)+parseInt(b))
↑ ↑ ↑ ↑
our coerce split sum
function to string in two both
Here a test :
const sum = (s) => (''+s).split('').reduce((a,b) => parseInt(a)+parseInt(b))
console.log(sum(12))
There are several approaches to sum digits of a number. You can convert it to a string but IDK if thats neccesary at all. You can do it with numerical operations.
var input = 2568,
sum = 0;
while (input) {
sum += input % 10;
input = Math.floor(input / 10);
}
console.log(sum);
Here's a fun short way to do it:
const number = 99
const temp = number.toString().split('')
const res = temp.reduce((a, c) => a + parseInt(c), 0) // 18
1.) Convert number to string
2.) Separate into individual numbers
3.) Use reduce to sum the numbers.
Your way would be the iterational way to solve this problem, but you can also use a recursive way.
Iterative solution (Imperative)
n.toString() Create String from number.
.split("") split string into chars.
.reduce(callback, startValue) reduces an array to a single value by applying the callback function to every element and updating the startValue.
(s, d) => s + parseInt(d) callback function which parses the element to an integer and adds it to s (the startValue).
0 startValue.
Recursive solution (Functional)
condition?then:else short-hand if notation.
n<10 only one digit => just return it.
n%10 the last digit of the current number (1234%10 = 4).
digital_root_recurse(...) call the function recursivly.
Math.floor(n / 10) Divide by 10 => shift dcimal point to left (1234 => 123)
... + ... add the last digit and the return value (digital root) of n/10 (1234 => 4 + root(123)).
function digital_root_string(n) {
return n.toString().split("").reduce((s, d) => s + parseInt(d), 0);
}
function digital_root_recurse(n) {
return n < 10 ? n : n % 10 + digital_root_recurse(Math.floor(n / 10));
}
console.log(digital_root_string(16));
console.log(digital_root_string(99));
console.log(digital_root_recurse(16));
console.log(digital_root_recurse(99));
The issue in your code is that you stored the length of n into z. The length is an integer, so both z[0] and [1] are undefined. The solution is to store the string into another variable and use that instead of z.
function digital_root(n) {
n = n.toString();
var l = n.length;
if (l === 2) {
return parseInt(n[0], 10) + parseInt(n[1], 10);
}
}
console.log( digital_root(16) );
Simply use var x = parseInt(n/10) + (n%10); and it will work for you.
function digital_root(n) {
var z = n.toString().length;
if (z == 2) {
var x = parseInt(n/10) + (n%10);
return x;
}
}
console.log( digital_root(16) );
console.log( digital_root(99) );
console.log( digital_root(62) );
Convert input to string, split it, convert each item back to number and sum them all:
function digital_root(n) {
return String(n).split('').map(Number).reduce((a,b) => a + b)
}
const result = digital_root(99);
console.log(result);

Get least significant digit including its value in a JavaScript

I would like to extract the least significant digit including its value from a number in JavaScript (so that no information is lost)
For example
12.0123323 -> 0.0000003
123299000 -> 9000
123001 -> 1
123001.01 -> 0.01
10000000 -> 10000000
etc...
Is there a neat way to do this?
Edit:
As people have noted because of Javascript:s way of handling numbers it can not represent 12.0123323, so let's assume it's a string in those corner cases.
You could check if the value is an integer number and choose a different replacement schema for getting the right least significant value.
function least(x) {
return x === Math.floor(x)
? +x.toString().replace(/.*(?=[1-9]0*$)/, '')
: +x.toString().replace(/\d(?=.*[1-9]$)/g, '0');
}
var array = [
12.0123323, // 0.0000003
123299000, // 9000
123001, // 1
123001.01, // 0.01
10000000 // 10000000
];
console.log(array.map(least));
.as-console-wrapper { max-height: 100% !important; top: 0; }
const least = num => [...num.toString()].reduceRight((res, d, i) => (+res ? (d === "." ? "." : "0") : d) + res, "");
Test Cases
It basically traverses the string presentation (toString) of the number from right to left (reduceRight) and if the current result has already a digit in it (+res) then
d === "." ? "." : "0"
it either takes over the dot or converts any other digit to 0. If there was no digit yet (:), it simply adds the current one d, and appends the already traversed part + res
If you rather like readable code:
function least(num){
var res = "";
for(var char of num.toString().split("").reverse()){
if(+res){
res = (char === "." ? "." : "0") + res;
} else {
res = char + res;
}
}
return res;
}
var foundNonzero = false
Number("324.034"
.split('')
.reverse()
.map((i)=>{
if(i==='.') return i
if(foundNonzero) return '0'
if(i!=='0'){
foundNonzero = true
}
return i
}).reverse().join(''))

Convert float to string with at least one decimal place (javascript)

Let me give you an example.
var a = 2.0;
var stringA = "" + a;
I will get: stringA = "2", but I want: stringA = "2.0".
I don't want to lose precision however, so if:
var b = 2.412;
var stringB = "" + b;
I want to get the standard: stringB = "2.412".
That's why toFixed() won't work here. Is there any other way to do it, than to explicitly check for whole numbers like this?:
if (a % 1 === 0)
return "" + a + ".0";
else
return "" + a;
There is a built-in function for this.
var a = 2;
var b = a.toFixed(1);
This rounds the number to one decimal place, and displays it with that one decimal place, even if it's zero.
If you want to append .0 to output from a Number to String conversion and keep precision for non-integers, just test for an integer and treat it specially.
function toNumberString(num) {
if (Number.isInteger(num)) {
return num + ".0"
} else {
return num.toString();
}
}
Input Output
3 "3.0"
3.4567 "3.4567"
For other people looking at this question, it just occurred to me, that to convert a float to a string with at least n decimal places, one could write:
function toAtLeastNDecimalPlaces(num, n) {
normal_conv = num.toString();
fixed_conv = num.toFixed(n);
return (fixed_conv.length > normal_conv.length ? fixed_conv : normal_conv);
}
Note that according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed, toFixed() will work for at most 20 decimal places. Therefore the function above will not work for n > 20.
Also, the function above does not have any special treatment for scientific notation (But neither do any other answers in this thread).
If a is your float do
var a = 2.0;
var b = (a % 1 == 0) ? a + ".0" : a.toString();
Edited: add reference and change to allow for .0
http://www.w3schools.com/jsref/jsref_tostring_number.asp
This solution tries to balance terseness and readability
const floatString = (n) => Number.isInteger(n) ? n.toFixed(1) : n.toString();

How can I pad a value with leading zeros?

What is the recommended way to zerofill a value in JavaScript? I imagine I could build a custom function to pad zeros on to a typecasted value, but I'm wondering if there is a more direct way to do this?
Note: By "zerofilled" I mean it in the database sense of the word (where a 6-digit zerofilled representation of the number 5 would be "000005").
I can't believe all the complex answers on here... Just use this:
var zerofilled = ('0000'+n).slice(-4);
let n = 1
var zerofilled = ('0000'+n).slice(-4);
console.log(zerofilled)
Simple way. You could add string multiplication for the pad and turn it into a function.
var pad = "000000";
var n = '5';
var result = (pad+n).slice(-pad.length);
As a function,
function paddy(num, padlen, padchar) {
var pad_char = typeof padchar !== 'undefined' ? padchar : '0';
var pad = new Array(1 + padlen).join(pad_char);
return (pad + num).slice(-pad.length);
}
var fu = paddy(14, 5); // 00014
var bar = paddy(2, 4, '#'); // ###2
Since ECMAScript 2017 we have padStart:
const padded = (.1 + "").padStart(6, "0");
console.log(`-${padded}`);
Before ECMAScript 2017
With toLocaleString:
var n=-0.1;
var res = n.toLocaleString('en', {minimumIntegerDigits:4,minimumFractionDigits:2,useGrouping:false});
console.log(res);
I actually had to come up with something like this recently.
I figured there had to be a way to do it without using loops.
This is what I came up with.
function zeroPad(num, numZeros) {
var n = Math.abs(num);
var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
var zeroString = Math.pow(10,zeros).toString().substr(1);
if( num < 0 ) {
zeroString = '-' + zeroString;
}
return zeroString+n;
}
Then just use it providing a number to zero pad:
> zeroPad(50,4);
"0050"
If the number is larger than the padding, the number will expand beyond the padding:
> zeroPad(51234, 3);
"51234"
Decimals are fine too!
> zeroPad(51.1234, 4);
"0051.1234"
If you don't mind polluting the global namespace you can add it to Number directly:
Number.prototype.leftZeroPad = function(numZeros) {
var n = Math.abs(this);
var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
var zeroString = Math.pow(10,zeros).toString().substr(1);
if( this < 0 ) {
zeroString = '-' + zeroString;
}
return zeroString+n;
}
And if you'd rather have decimals take up space in the padding:
Number.prototype.leftZeroPad = function(numZeros) {
var n = Math.abs(this);
var zeros = Math.max(0, numZeros - n.toString().length );
var zeroString = Math.pow(10,zeros).toString().substr(1);
if( this < 0 ) {
zeroString = '-' + zeroString;
}
return zeroString+n;
}
Cheers!
XDR came up with a logarithmic variation that seems to perform better.
WARNING: This function fails if num equals zero (e.g. zeropad(0, 2))
function zeroPad (num, numZeros) {
var an = Math.abs (num);
var digitCount = 1 + Math.floor (Math.log (an) / Math.LN10);
if (digitCount >= numZeros) {
return num;
}
var zeroString = Math.pow (10, numZeros - digitCount).toString ().substr (1);
return num < 0 ? '-' + zeroString + an : zeroString + an;
}
Speaking of performance, tomsmeding compared the top 3 answers (4 with the log variation). Guess which one majorly outperformed the other two? :)
Modern browsers now support padStart, you can simply now do:
string.padStart(maxLength, "0");
Example:
string = "14";
maxLength = 5; // maxLength is the max string length, not max # of fills
res = string.padStart(maxLength, "0");
console.log(res); // prints "00014"
number = 14;
maxLength = 5; // maxLength is the max string length, not max # of fills
res = number.toString().padStart(maxLength, "0");
console.log(res); // prints "00014"
Here's what I used to pad a number up to 7 characters.
("0000000" + number).slice(-7)
This approach will probably suffice for most people.
Edit: If you want to make it more generic you can do this:
("0".repeat(padding) + number).slice(-padding)
Edit 2: Note that since ES2017 you can use String.prototype.padStart:
number.toString().padStart(padding, "0")
Unfortunately, there are a lot of needless complicated suggestions for this problem, typically involving writing your own function to do math or string manipulation or calling a third-party utility. However, there is a standard way of doing this in the base JavaScript library with just one line of code. It might be worth wrapping this one line of code in a function to avoid having to specify parameters that you never want to change like the local name or style.
var amount = 5;
var text = amount.toLocaleString('en-US',
{
style: 'decimal',
minimumIntegerDigits: 3,
useGrouping: false
});
This will produce the value of "005" for text. You can also use the toLocaleString function of Number to pad zeros to the right side of the decimal point.
var amount = 5;
var text = amount.toLocaleString('en-US',
{
style: 'decimal',
minimumFractionDigits: 2,
useGrouping: false
});
This will produce the value of "5.00" for text. Change useGrouping to true to use comma separators for thousands.
Note that using toLocaleString() with locales and options arguments is standardized separately in ECMA-402, not in ECMAScript. As of today, some browsers only implement basic support, i.e. toLocaleString() may ignore any arguments.
Complete Example
If the fill number is known in advance not to exceed a certain value, there's another way to do this with no loops:
var fillZeroes = "00000000000000000000"; // max number of zero fill ever asked for in global
function zeroFill(number, width) {
// make sure it's a string
var input = number + "";
var prefix = "";
if (input.charAt(0) === '-') {
prefix = "-";
input = input.slice(1);
--width;
}
var fillAmt = Math.max(width - input.length, 0);
return prefix + fillZeroes.slice(0, fillAmt) + input;
}
Test cases here: http://jsfiddle.net/jfriend00/N87mZ/
The quick and dirty way:
y = (new Array(count + 1 - x.toString().length)).join('0') + x;
For x = 5 and count = 6 you'll have y = "000005"
Here's a quick function I came up with to do the job. If anyone has a simpler approach, feel free to share!
function zerofill(number, length) {
// Setup
var result = number.toString();
var pad = length - result.length;
while(pad > 0) {
result = '0' + result;
pad--;
}
return result;
}
ECMAScript 2017:
use padStart or padEnd
'abc'.padStart(10); // " abc"
'abc'.padStart(10, "foo"); // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
More info:
https://github.com/tc39/proposal-string-pad-start-end
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
I often use this construct for doing ad-hoc padding of some value n, known to be a positive, decimal:
(offset + n + '').substr(1);
Where offset is 10^^digits.
E.g., padding to 5 digits, where n = 123:
(1e5 + 123 + '').substr(1); // => 00123
The hexadecimal version of this is slightly more verbose:
(0x100000 + 0x123).toString(16).substr(1); // => 00123
Note 1: I like #profitehlolz's solution as well, which is the string version of this, using slice()'s nifty negative-index feature.
I really don't know why, but no one did it in the most obvious way. Here it's my implementation.
Function:
/** Pad a number with 0 on the left */
function zeroPad(number, digits) {
var num = number+"";
while(num.length < digits){
num='0'+num;
}
return num;
}
Prototype:
Number.prototype.zeroPad=function(digits){
var num=this+"";
while(num.length < digits){
num='0'+num;
}
return(num);
};
Very straightforward, I can't see any way how this can be any simpler. For some reason I've seem many times here on SO, people just try to avoid 'for' and 'while' loops at any cost. Using regex will probably cost way more cycles for such a trivial 8 digit padding.
In all modern browsers you can use
numberStr.padStart(numberLength, "0");
function zeroFill(num, numLength) {
var numberStr = num.toString();
return numberStr.padStart(numLength, "0");
}
var numbers = [0, 1, 12, 123, 1234, 12345];
numbers.forEach(
function(num) {
var numString = num.toString();
var paddedNum = zeroFill(numString, 5);
console.log(paddedNum);
}
);
Here is the MDN reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
I use this snippet to get a five-digits representation:
(value+100000).toString().slice(-5) // "00123" with value=123
The power of Math!
x = integer to pad
y = number of zeroes to pad
function zeroPad(x, y)
{
y = Math.max(y-1,0);
var n = (x / Math.pow(10,y)).toFixed(y);
return n.replace('.','');
}
This is the ES6 solution.
function pad(num, len) {
return '0'.repeat(len - num.toString().length) + num;
}
alert(pad(1234,6));
Not that this question needs more answers, but I thought I would add the simple lodash version of this.
_.padLeft(number, 6, '0')
I didn't see anyone point out the fact that when you use String.prototype.substr() with a negative number it counts from the right.
A one liner solution to the OP's question, a 6-digit zerofilled representation of the number 5, is:
console.log(("00000000" + 5).substr(-6));
Generalizing we'll get:
function pad(num, len) { return ("00000000" + num).substr(-len) };
console.log(pad(5, 6));
console.log(pad(45, 6));
console.log(pad(345, 6));
console.log(pad(2345, 6));
console.log(pad(12345, 6));
Don't reinvent the wheel; use underscore string:
jsFiddle
var numToPad = '5';
alert(_.str.pad(numToPad, 6, '0')); // Yields: '000005'
After a, long, long time of testing 15 different functions/methods found in this questions answers, I now know which is the best (the most versatile and quickest).
I took 15 functions/methods from the answers to this question and made a script to measure the time taken to execute 100 pads. Each pad would pad the number 9 with 2000 zeros. This may seem excessive, and it is, but it gives you a good idea about the scaling of the functions.
The code I used can be found here:
https://gist.github.com/NextToNothing/6325915
Feel free to modify and test the code yourself.
In order to get the most versatile method, you have to use a loop. This is because with very large numbers others are likely to fail, whereas, this will succeed.
So, which loop to use? Well, that would be a while loop. A for loop is still fast, but a while loop is just slightly quicker(a couple of ms) - and cleaner.
Answers like those by Wilco, Aleksandar Toplek or Vitim.us will do the job perfectly.
Personally, I tried a different approach. I tried to use a recursive function to pad the string/number. It worked out better than methods joining an array but, still, didn't work as quick as a for loop.
My function is:
function pad(str, max, padder) {
padder = typeof padder === "undefined" ? "0" : padder;
return str.toString().length < max ? pad(padder.toString() + str, max, padder) : str;
}
You can use my function with, or without, setting the padding variable. So like this:
pad(1, 3); // Returns '001'
// - Or -
pad(1, 3, "x"); // Returns 'xx1'
Personally, after my tests, I would use a method with a while loop, like Aleksandar Toplek or Vitim.us. However, I would modify it slightly so that you are able to set the padding string.
So, I would use this code:
function padLeft(str, len, pad) {
pad = typeof pad === "undefined" ? "0" : pad + "";
str = str + "";
while(str.length < len) {
str = pad + str;
}
return str;
}
// Usage
padLeft(1, 3); // Returns '001'
// - Or -
padLeft(1, 3, "x"); // Returns 'xx1'
You could also use it as a prototype function, by using this code:
Number.prototype.padLeft = function(len, pad) {
pad = typeof pad === "undefined" ? "0" : pad + "";
var str = this + "";
while(str.length < len) {
str = pad + str;
}
return str;
}
// Usage
var num = 1;
num.padLeft(3); // Returns '001'
// - Or -
num.padLeft(3, "x"); // Returns 'xx1'
First parameter is any real number, second parameter is a positive integer specifying the minimum number of digits to the left of the decimal point and third parameter is an optional positive integer specifying the number if digits to the right of the decimal point.
function zPad(n, l, r){
return(a=String(n).match(/(^-?)(\d*)\.?(\d*)/))?a[1]+(Array(l).join(0)+a[2]).slice(-Math.max(l,a[2].length))+('undefined'!==typeof r?(0<r?'.':'')+(a[3]+Array(r+1).join(0)).slice(0,r):a[3]?'.'+a[3]:''):0
}
so
zPad(6, 2) === '06'
zPad(-6, 2) === '-06'
zPad(600.2, 2) === '600.2'
zPad(-600, 2) === '-600'
zPad(6.2, 3) === '006.2'
zPad(-6.2, 3) === '-006.2'
zPad(6.2, 3, 0) === '006'
zPad(6, 2, 3) === '06.000'
zPad(600.2, 2, 3) === '600.200'
zPad(-600.1499, 2, 3) === '-600.149'
The latest way to do this is much simpler:
var number = 2
number.toLocaleString(undefined, {minimumIntegerDigits:2})
output: "02"
Just another solution, but I think it's more legible.
function zeroFill(text, size)
{
while (text.length < size){
text = "0" + text;
}
return text;
}
This one is less native, but may be the fastest...
zeroPad = function (num, count) {
var pad = (num + '').length - count;
while(--pad > -1) {
num = '0' + num;
}
return num;
};
My solution
Number.prototype.PadLeft = function (length, digit) {
var str = '' + this;
while (str.length < length) {
str = (digit || '0') + str;
}
return str;
};
Usage
var a = 567.25;
a.PadLeft(10); // 0000567.25
var b = 567.25;
b.PadLeft(20, '2'); // 22222222222222567.25
With ES6+ JavaScript:
You can "zerofill a number" with something like the following function:
/**
* #param number The number
* #param minLength Minimal length for your string with leading zeroes
* #return Your formatted string
*/
function zerofill(nb, minLength) {
// Convert your number to string.
let nb2Str = nb.toString()
// Guess the number of zeroes you will have to write.
let nbZeroes = Math.max(0, minLength - nb2Str.length)
// Compute your result.
return `${ '0'.repeat(nbZeroes) }${ nb2Str }`
}
console.log(zerofill(5, 6)) // Displays "000005"
With ES2017+:
/**
* #param number The number
* #param minLength Minimal length for your string with leading zeroes
* #return Your formatted string
*/
const zerofill = (nb, minLength) => nb.toString().padStart(minLength, '0')
console.log(zerofill(5, 6)) // Displays "000005"
Use recursion:
function padZero(s, n) {
s = s.toString(); // In case someone passes a number
return s.length >= n ? s : padZero('0' + s, n);
}
Some monkeypatching also works
String.prototype.padLeft = function (n, c) {
if (isNaN(n))
return null;
c = c || "0";
return (new Array(n).join(c).substring(0, this.length-n)) + this;
};
var paddedValue = "123".padLeft(6); // returns "000123"
var otherPadded = "TEXT".padLeft(8, " "); // returns " TEXT"
function pad(toPad, padChar, length){
return (String(toPad).length < length)
? new Array(length - String(toPad).length + 1).join(padChar) + String(toPad)
: toPad;
}
pad(5, 0, 6) = 000005
pad('10', 0, 2) = 10 // don't pad if not necessary
pad('S', 'O', 2) = SO
...etc.
Cheers

Modulo in JavaScript - large number

I try to calculate with JS' modulo function, but don't get the right result (which should be 1). Here is a hardcoded piece of code.
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
Whats the problem here?
Regards,
Benedikt
For an IBAN calculation form a normal bankaccount number I end up with a very large number contained in a string datatype. From this large number I have to find the rest when divided by 97 -> large number % 97.
As soon as I convert the datatype to an integer I get an overflow resulting in a negative integer and eventually a wrong rest value. As I saw some verbose pieces of code (which also gave wrong outcome), I could not resist to share my own. Credits go to Finding Modulus of a Very Large Number with a Normal Number
modulo: function(divident, divisor) {
var partLength = 10;
while (divident.length > partLength) {
var part = divident.substring(0, partLength);
divident = (part % divisor) + divident.substring(partLength);
}
return divident % divisor;
}
N.B.
I use 10 positions here as this is smaller than the 15 (and some) positions of max integer in JavaScript, it results in a number bigger than 97 and it's a nice round number. The first two arguments matter.
A bunch of improvements to Benedikt's version: "cRest += '' + cDivident;" is a bugfix; parseInt(divisor) makes it possible to pass both arguments as strings; check for empty string at the end makes it always return numerical values; added var statements so it's not using global variables; converted foreach to old-style for so it works in browsers with older Javascript; fixed the cRest == 0; bug (thanks #Dan.StackOverflow).
function modulo (divident, divisor) {
var cDivident = '';
var cRest = '';
for (var i in divident ) {
var cChar = divident[i];
var cOperator = cRest + '' + cDivident + '' + cChar;
if ( cOperator < parseInt(divisor) ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) {
cRest = '';
}
cDivident = '';
}
}
cRest += '' + cDivident;
if (cRest == '') {
cRest = 0;
}
return cRest;
}
For those who simply want to copy&paste a working (functional) solution in ES6 to check IBANs:
function isIBAN(s){
const rearranged = s.substring(4,s.length) + s.substring(0,4);
const numeric = Array.from(rearranged).map(c =>(isNaN(parseInt(c)) ? (c.charCodeAt(0)-55).toString() : c)).join('');
const remainder = Array.from(numeric).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % 97,0);
return remainder === 1;}
You could even write it as a one-liner.
The modulo operation is performed on the array of integers storing the actual number (divident, applied as string to function):
function modulo(divident, divisor){
return Array.from(divident).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % divisor,0);
};
This works because Modulo is distributive over addition, substraction and multiplication:
(a+b)%m = ((a%m)+(b%m))%m
(a-b)%m = ((a%m)-(b%m))%m
(ab)%m = ((a%m)(b%m))%m
The IBAN function transpiled to ES5 looks like:
function (s) {
var rearranged = s.substring(4, s.length) + s.substring(0, 4);
var numeric = Array.from(rearranged).map(function (c) { return (isNaN(parseInt(c)) ? (c.charCodeAt(0) - 55).toString() : c); }).join('');
var remainder = Array.from(numeric).map(function (c) { return parseInt(c); }).reduce(function (remainder, value) { return (remainder * 10 + value) % 97; }, 0);
return remainder === 1;
};
looks like you've fallen victim to this: What is JavaScript's highest integer value that a Number can go to without losing precision?
just to reiterate what's in the other thread:
they are 64-bit floating point values, the largest exact integral value is 2^53. however, from the spec section [8.5: Number Type]:
Some ECMAScript operators deal only with integers in the range −2^31 through 2^31−1, inclusive, or in the range 0 through 2^32−1, inclusive. These operators accept any value of the Number type but first convert each such value to one of 2^32 integer values. See the descriptions of the ToInt32 and ToUint32 operators in sections 0 and 0, respectively
But credit where credit is due. Jimmy got the accepted answer over there for doing the legwork (well, googling).
Finally, my solution:
function modulo (divident, divisor) {
cDivident = '';
cRest = '';
for each ( var cChar in divident ) {
cOperator = cRest + '' + cDivident + '' + cChar;
if ( cOperator < divisor ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) cRest = '';
cDivident = '';
}
}
return cRest;
}
Silent Matt has developed a Javascript library for Big Integers. It could solve this issue too.

Categories

Resources