I'm currently producing a JavaScript driven mathematics package, which focuses on rounding to various significant figures (S.F.) but I've run into a problem that I'm struggling to solve.
More on this problem later, but first some background for you.
The program is designed to select a completely random number within a given range and then automatically work out that number's relevant significant figures; for example:
Random Number: 0.097027 S.Fs: 9, 7, 0, 2, 7
Here is a screenshot of what I have produced to give you a visual representation:
As you can see, once the user has selected their number, they are then given the opportunity to click on four separate 'SF' buttons to view their random number presented to 1, 2, 3 and 4 S.Fs respectively.
For each S.F (1-4) the random number is rounded down, rounded up and rounded off to X SF and a scale below gives the user a more visual presentation to show why the SF value has been chosen by the program.
I've already written the vast majority of the code for this and tested it and so far the numbers are coming out how I'm expecting them to. Well nearly...
In the example I've given (0.097027); as you can see on the image I've included, the data for 4 S.F is absolutely correct and outputted accurately.
When I click on to the 3 SF button, I'd expect to see the following:
Random Number: 0.097027 3 S.F Rounded Up/Down/Off: 0.0970
However, what I'm actually getting is:
Random Number: 0.097027 3 S.F Rounded Up/Down/Off: 0.097
The program hasn't displayed the additional zero. This is a perfect example of a number in my program ending in a zero and in this case the zero is really significant and must be displayed.
The data is usually correct but there appears to be an issue with outputting significant zeros at the right time. I've researched the toFixed(x) method and if I assign toFixed(4) I get the correct required output, but because my numbers are generated randomly each time, they can range from a length of 5 figures, e.g. 89.404 up to > 10, e.g. `0.000020615.
So it looks like the toFixed method needs to be flexible/dynamic, e.g. toFixed(n) with a function run beforehand to determine exactly how many trailing zeros are needed?
Here are some key excerpts from my current solution for your consideration:
function generateNum() {
do {
genNumber = Math.random() * Math.pow (10, randomRange(-5, 5));
//Round
genNumber = roundToNSF(genNumber, 5, 0);
// This number must contain >1 digit which is 1 to 9 inclusive otherwise we may have e.g. 100. Rounding 100
}
while (!countNonZero(genNumber) || genNumber < 1E-05 || genNumber == 0);
//Round
genNumber = roundToNSF(genNumber, 5, 0);
genNumber = String(genNumber);
genNumber = Number(genNumber);
}
//----------------------------------------------------------------------------
function randomRange(min, max) {
/**
* Returns a random integer between min (inclusive) and max (inclusive)
* Using Math.round() will give you a non-uniform distribution!
*/
return Math.floor(Math.random() * (max - min + 1)) + min;
}
//---------------------------------------------------------------------------
//Click SF3 Button to reveal the data
function showSF3() {
//Remove any CSS properties on the buttons from previous use
removeButtonCSS();
document.getElementById('SFRounded').style.display = "block";
document.getElementById('scale').style.display = "block";
document.getElementById("SF3").className = document.getElementById("SF3").className + "buttonClick"; // this removes the blue border class
//Clear text
deleteRounded();
deleteScale();
//Run calculation
calculateAnswer();
//alert(genNumber.toFixed(4));
for (i = 3; i < 4; i++)
{
//Add The new data
sfRoundedTextBlock = document.getElementById('SFRounded');
//alert(downArray[i].toFixed(4));
//Data output to HTML.
sfRoundedTextBlock.innerHTML = sfRoundedTextBlock.innerHTML + '<p><strong>Number: </strong></br>' + String(genNumber) +
'</br>' + '<strong>Rounded down to ' + i + ' SF:</br></strong>' + downArray[i] + '</br>' +
'<strong>Rounded up to ' + i + ' SF:</br></strong>' + upArray[i] + '</br><strong>Rounded off to ' + i + ' SF:</br></strong>'
+ roundedArray[i] + '</br>' + '(See the scale below for why we choose <strong>' + roundedArray[i] + '</strong> as the rounded off value.)</p>';
}
}
//----------------------------------------------------------------------
var roundedArray = [];
var upArray = [];
var downArray = [];
var temp;
function calculateAnswer() {
//Clear Arrays
roundedArray = [];
upArray = [];
downArray = [];
// Work out the answer:
for (i = 0; i < 4; i++) {
var nSF = i + 1;
// Round OFF ...
temp = roundToNSF(genNumber, nSF, 0);
// We actually have to do this twice ...
roundedArray[nSF] = roundToNSF(temp, nSF, 0);
// Round UP ...
upArray[nSF] = roundToNSF(genNumber, nSF, 1);
// Round DOWN ...
downArray[nSF] = roundToNSF(genNumber, nSF, -1);
// e.g. x = 0.0098 rounded to 1SF is 0.010 initially (take the log of 0.0098 and try it!).
};
};
//-------------------------------------------------------------------------
//Globals
var aNumber;
var digits;
var way;
function roundToNSF(aNumber, digits, way){
// Round a number to n significant figures (can use roundToNDP provided we know how many decimal places):
if (way == undefined) { way = 0; }; // default is round off
if (aNumber !=0) {
if (aNumber > 0)
{
z = log10(aNumber);
}
else
{
z = log10(-aNumber);
};
z = Math.floor(z);
var nDP = digits - z - 1; // Rounding to nDP decimal places is equivalent to rounding to digits significant figures ...
var roundedNumber = roundToNDP(aNumber, nDP, way);
}
else {
roundedNumber = aNumber; // Number is zero ...
};
return Number(roundedNumber);
};
//---------------------------------------------------------------------------------
Update:
I'm still continuing to try and find a solution for this problem and an approach I have recently taken is to convert my randomly generated number into a searchable string variable and then use the indexOf(".") command to find the position of the decimal point (dp).
Then I've searched through my number, starting from the position of the dp to find the first instance of a significant, non-zero number [1-9].
var genNumber = 0.097027;
var rString = String(genNumber);
var positionofDP = rString.indexOf(".");
var regexp = /[1-9]/;
var positionofNonZero = Number(rString.search(regexp, positionofDP)); // Output would be '5'
I have then been able to target my search further, to determine whether my first significant number has any 'problematic' zeros in the immediate digits after it.
If there are any, then I set a Boolean variable to 'true' and then in a separate function create further text strings of my rounded off/down/up numbers, so I can then physically choose to add a '0' on to the end of the existing numerical characters.
This approach does work for me in isolated cases, but with my random number length ranging from 5-12 digits long, it still isn't dealing with all scenarios.
Maybe I need to create a dynamic toFixed(i) function? Any ideas would be greatly welcomed.
Instead of playing with the fixed points on an Int, you could manage the string directly.
Here's a link to a little fiddle: http://jsfiddle.net/5rw5G/4/
This not intended to completely/accurately solve your problem, but might help you see another solution.
function getRoundedSFs(num, SFCount) {
// Match every "leading zeros" before and after the .
var matches = num.toString().match(/^-?(0+)\.(0*)/);
// starting with "0."
if (matches) {
var firstIndex = matches[0].length;
var prefix = matches[0];
sf = Number(num.toString().substring(firstIndex, firstIndex + SFCount + 1));
sf = Math.round(sf / 10);
sf = prefix + sf.toString();
return Number(sf).toFixed(matches[2].length+SFCount);
}
// starting with something else like -5.574487436097115
else {
matches = num.toString().match(/^(-?(\d+))\.(\d+)/);
var decimalShift = SFCount - matches[2].length;
var rounded = Math.round(num * Math.pow(10, decimalShift));
rounded /= Math.pow(10, decimalShift);
return rounded.toFixed(decimalShift);
}
}
I've gone away again and I think I have now finally managed solve my initial problem.
There was a degree of confusion on my part surrounding when to use toFixed and toPrecision. I had previously attempted to convert my rounded up, down and off numbers into strings and then subsequently search through each of these to find the decimal point (".") and then work out the amount of trailing numbers, in order to then generate the correct toFixed point.
However, this was very hit and miss, given that my random number could be up to 12 digits, so what I've now done is to properly utilise toPrecision instead. For each 'SF button' (1-4) I have used the corresponding toPrecision point, e.g for SF1:
sfRoundedTextBlock.innerHTML = sfRoundedTextBlock.innerHTML + '<p><strong>Number: </strong></br>' + String(genNumber) +
'</br>' + '<strong>Rounded down to ' + i + ' SF:</br></strong>' + downArray[i].toPrecision(1) + '</br>' +
'<strong>Rounded up to ' + i + ' SF:</br></strong>' + upArray[i].toPrecision(1) + '</br><strong>Rounded off to ' + i + ' SF:</br></strong>'
+ roundedArray[i].toPrecision(1) + '</br>' + '(See the scale below for why we choose <strong>' + roundedArray[i].toPrecision(1) + '</strong> as the rounded off value.)</p>';
//Add The new scale data (Rounded Down)
downTextBlock = document.getElementById('down');
document.getElementById("down").innerHTML = String(downArray[i].toPrecision(1));
//Add The new scale data (Rounded Up)
upTextBlock = document.getElementById('up');
document.getElementById("up").innerHTML = String(upArray[i].toPrecision(1));
This was now giving me accurate results on every occasion, but there was still one hurdle left to jump. Occasionally I would reach a random scenario where scientific notation would have to be included in my outputted answer, e.g. 21819 rounded down to 1 SF, would read out at 2e+4 instead of 20000.
To combat this I setup my up, down and rounded figures into searchable strings, and then looked through these to find any illegal/scientific characters [a-z]. If I found any, I executed a slightly different version of my output which made use of parseFloat, which stripped out the scientific notation and displayed the correct figures:
//Convert Up, Down and Rounded into Strings based on their precision
var upString = String(upArray[i].toPrecision(1));
var downString = String(downArray[i].toPrecision(1));
var roundedString = String(roundedArray[i].toPrecision(1));
//Set up a regexp to search for characters [a-z], i.e. non-numeric
var regexp = /[a-z]/g;
//Search the up, down and rounded strings for non-numeric characters
var upResult = upString.match(regexp);
var downResult = downString.match(regexp);
var roundedResult = roundedString.match(regexp);
//If any of these strings contain a letter (non-numeric) we need to add in parseFloat to strip away the scientific notation included.
var containsChar = false;
if (upResult != null || downResult != null || roundedResult != null)
{
containsChar = true;
//alert("There is SN included here");
}
//Add The new data
sfRoundedTextBlock = document.getElementById('SFRounded');
if (containsChar == true)
{
sfRoundedTextBlock.innerHTML = sfRoundedTextBlock.innerHTML + '<p><strong>Number: </strong></br>' + String(genNumber) +
'</br>' + '<strong>Rounded down to ' + i + ' SF:</br></strong>' + parseFloat(downArray[i].toPrecision(1)) + '</br>' +
'<strong>Rounded up to ' + i + ' SF:</br></strong>' + parseFloat(upArray[i].toPrecision(1)) + '</br><strong>Rounded off to ' + i + ' SF:</br></strong>'
+ parseFloat(roundedArray[i].toPrecision(1)) + '</br>' + '(See the scale below for why we choose <strong>' + parseFloat(roundedArray[i].toPrecision(1)) + '</strong> as the rounded off value.)</p>';
//Add The new scale data (Rounded Down)
downTextBlock = document.getElementById('down');
document.getElementById("down").innerHTML = String(parseFloat(downArray[i].toPrecision(1)));
//Add The new scale data (Rounded Up)
upTextBlock = document.getElementById('up');
document.getElementById("up").innerHTML = String(parseFloat(upArray[i].toPrecision(1)));
}
Having tested this extensively it seems to be working as hoped.
Related
In my current project, I am creating random mathematics questionnaires for abacus student. So the exam page will serve sums one by one. Based on the student level I am generationg sums at front end using jquery and rendering to get student answer for validation. In a particular level I need to generate divisions with zero remainder.
So, I am using below function to generate the sum which is returning undefined sometimes.
tripleDigitSingleDigitWithoutRemainder: function()
{
var dividend = BOBASSESSMENT.general.randomIntFromInterval(100, 999);
var divisor = BOBASSESSMENT.general.randomIntFromInterval(2, 9);
console.log("out: " + dividend + "_" + divisor);
console.log("remainder: " + (dividend % divisor));
var result_val = "";
// result_val = dividend % divisor;
if(dividend % divisor != 0)
{
console.log('loop_again');
BOBASSESSMENT.general.tripleDigitSingleDigitWithoutRemainder();
}else{
result_val = dividend + "_" + divisor;
console.log("return: " + result_val);
}
console.log("final_return: " + result_val);
return result_val;
}
hence, please help me here to do further.
the requirement is to show question one by one and I need a dividend value and divisor value which does give remainder as 0. It means 16 % 2 = 0 not like 16 % 3 = 1.
Can you please some one help here.
As discussed in the comments here's a way to use a loop to try again with different values instead of recursion:
tripleDigitSingleDigitWithoutRemainder: function()
{
for(;;)
{
var dividend = BOBASSESSMENT.general.randomIntFromInterval(100, 999);
var divisor = BOBASSESSMENT.general.randomIntFromInterval(2, 9);
if(dividend % divisor == 0)
{
var result_val = dividend + "_" + divisor;
console.log("return: " + result_val);
return result_val;
}
}
}
Here we have an infinite loop and we keep looping until we have a valid problem and then immediately return when we do. for(;;) is one way of writing an infinite loop: there are others e.g. while (true) { ... } if that's clearer - up to you.
(However I prefer the approach in Wimanicesir's answer which constructs a correct value rather than just trying repeatedly until we find one, which may take many more goes.)
As said in the comments. Isn't it better to just create a working division by creating it with a product?
function generate() {
// Numbers [2-9]
var small = Math.floor(Math.random() * 8) + 2
// This will give the limit of current divider
var limit = Math.ceil(900 / small)
// We check the minimum now
var minimum = Math.floor(100 / small)
// We create a new random with given limit
var big = Math.ceil(Math.random() * limit) + minimum
// Create the product
var product = big * small;
return { question: product + ' / ' + small, answer: big }
}
console.log(generate())
How can I construct a float value from two whole values?
var amountBeforeComma = 5;
var amountAfterComma = 234;
var amount = ?? //amount == 5.234
There's the math way, using logarithms:
var amountBeforeComma = 5;
var amountAfterComma = 234;
var amount = amountBeforeComma +
amountAfterComma * Math.pow(10, -(Math.floor(Math.log10(amountAfterComma)) + 1));
console.log(amount);
Math.log10(amountAfterComma) gives us the common logarithm of amountAfterComma, then Math.floor(...) on that gives us the characteristic of it (2 in your example), which is (as the linked Wikipedia page puts it) "how many places the decimal point must be moved so that it is just to the right of the first significant digit". Then we add one to that and make it a negative (e.g., -3 in your example) and raise raise 10 to that power to get a value to multiply it by (0.001 in your example) to put it where it should go. Add the amountBeforeComma and we're done.
Or the string then parse way:
var amountBeforeComma = 5;
var amountAfterComma = 234;
var amount = parseFloat(amountBeforeComma + "." + amountAfterComma);
console.log(amount);
(Or use +(amountBeforeComma + "." + amountAfterComma) to convert with implicit coercion rather than explicit parsing.)
Since no one mentioned... There's the JavaScript way:
var num = +(amountBeforeComma + "." + amountAfterComma);
You can make it by casting numbers to strings and then parsing it as float.
var amount = parseFloat(amountBeforeComma + '.' + amountAfterComma);
For some reason I'm having difficulty getting this while loop to work. It keeps crashing my browser whenever I try to test it out, and in the one case that I was able to see the results of the loop in the console, all I saw was NaN printed several times. Is there something I've forgotten in my code?
<div id="output"></div>
<script>
var starting = prompt("What is your starting balance?");
var target = prompt("What is your target balance?");
var interest = prompt("What is your interest rate?");
var periods = 0;
var current = starting;
var greaterThan = false;
while (greaterThan === false) {
if (current < target) {
current = current + (current * interest);
periods++;
} else {
greaterThan = true;
alert("it took " + periods + " periods to make your starting balance greater than your target balance.");
document.querySelector('#output').textContent = "to grow an initial investment of " + starting + " to " + target + " at a " + interest + " interest rate will require " + periods + " investment periods.";
}
}
</script>
The one problem I could see is, all your input values are string, not numbers so they are doing string comparison not numeric
var starting = +prompt("What is your starting balance?") ||0;
var target = +prompt("What is your target balance?")||0;
var interest = +prompt("What is your interest rate?")||1;
The + in front of prompt() is the unary plus operator
You are forgetting to convert the result from prompt from a string into a number.
var starting = parseFloat(prompt("What is your starting balance?"));
Do the same thing to the other numbers that are input by the user from the prompt.
First you need to convert your input into an integer value. The input from the prompt is a string. even if you enter 1 or 10 or any number. You can use parseInt() for that. and because you are asking for interest rate, i think any user would enter something like 2. 5, or 10 as a percentile. not 0.1, or 0.05. Even if he does, the parseInt() function can't get it right because 0.05 is not an integer value. You can use parseFloat for that. so i suggest you look at my implementation of your code below. also, i have omitted the if else statements because they weren't necessary and would only make the code more complex.
<div id="output"></div>
<script type="text/javascript">
var starting = parseInt(prompt("What is your starting balance?"));
var target = parseInt(prompt("What is your target balance?"));
var interest = parseInt(prompt("What is your interest rate?"));
var periods = 0;
var intrate = interest/100;
var current = starting;
while (current< target) {
current += (current*intrate);
periods += 1;
}
alert("it took " + periods + " periods to make your starting balance greater than your target balance.");
document.querySelector('#output').textContent = "to grow an initial investment of " + starting + " to " + target + " at a " + interest + " interest rate will require " + periods + " investment periods.";
</script>
For an ObjectId in MongoDB, I work with a 24 digit hexadecimal number. Because I need to keep track of a second collection, I need to add 1 to this hexadecimal number.
In my case, here's my value
var value = "55a98f19b27585d81922ba0b"
What I'm looking for is
var newValue = "55a98f19b25785d81922ba0c"
I tried to create a function for this
function hexPlusOne(hex) {
var num = (("0x" + hex) / 1) + 1;
return num.toString(16);
}
This works with smaller hex numbers
hexPlusOne("eeefab")
=> "eeefac"
but it fails miserably for my hash
hexPlusOne(value)
=> "55a98f19b275840000000000"
Is there a better way to solve this?
This version will return a string as long as the input string, so the overflow is ignored in case the input is something like "ffffffff".
function hexIncrement(str) {
var hex = str.match(/[0-9a-f]/gi);
var digit = hex.length;
var carry = 1;
while (digit-- && carry) {
var dec = parseInt(hex[digit], 16) + carry;
carry = Math.floor(dec / 16);
dec %= 16;
hex[digit] = dec.toString(16);
}
return(hex.join(""));
}
document.write(hexIncrement("55a98f19b27585d81922ba0b") + "<BR>");
document.write(hexIncrement("ffffffffffffffffffffffff"));
This version may return a string which is 1 character longer than the input string, because input like "ffffffff" carries over to become "100000000".
function hexIncrement(str) {
var hex = str.match(/[0-9a-f]/gi);
var digit = hex.length;
var carry = 1;
while (digit-- && carry) {
var dec = parseInt(hex[digit], 16) + carry;
carry = Math.floor(dec / 16);
dec %= 16;
hex[digit] = dec.toString(16);
}
if (carry) hex.unshift("1");
return(hex.join(""));
}
document.write(hexIncrement("55a98f19b27585d81922ba0b") + "<BR>");
document.write(hexIncrement("ffffffffffffffffffffffff"));
I was curious te see whether user2864740's suggestion of working with 12-digit chunks would offer any advantage. To my surprise, even though the code looks more complicated, it's actually around twice as fast. But the first version runs 500,000 times per second too, so it's not like you're going to notice in the real world.
function hexIncrement(str) {
var result = "";
var carry = 1;
while (str.length && carry) {
var hex = str.slice(-12);
if (/^f*$/i.test(hex)) {
result = hex.replace(/f/gi, "0") + result;
carry = 1;
} else {
result = ("00000000000" + (parseInt(hex, 16) + carry).toString(16)).slice(-hex.length) + result;
carry = 0;
}
str = str.slice(0,-12);
}
return(str.toLowerCase() + (carry ? "1" : "") + result);
}
document.write(hexIncrement("55a98f19b27585d81922ba0b") + "<BR>");
document.write(hexIncrement("000000000000ffffffffffff") + "<BR>");
document.write(hexIncrement("0123456789abcdef000000000000ffffffffffff"));
The error comes from attempting to covert the entire 24-digit hex value to a number first because it won't fit in the range of integers JavaScript can represent distinctly2. In doing such a conversion to a JavaScript number some accuracy is lost.
However, it can be processed as multiple (eg. two) parts: do the math on the right part and then the left part, if needed due to overflow1. (It could also be processed one digit at a time with the entire addition done manually.)
Each chunk can be 12 hex digits in size, which makes it an easy split-in-half.
1 That is, if the final num for the right part is larger than 0xffffffffffff, simply carry over (adding) one to the left part. If there is no overflow then the left part remains untouched.
2 See What is JavaScript's highest integer value that a Number can go to without losing precision?
The range is 2^53, but the incoming value is 16^24 ~ (2^4)^24 ~ 2^(4*24) ~ 2^96; still a valid number, but outside the range of integers that can be distinctly represented.
Also, use parseInt(str, 16) instead of using "0x" + str in a numeric context to force the conversion, as it makes the intent arguably more clear.
var number = 1310;
should be left alone.
var number = 120;
should be changed to "0120";
var number = 10;
should be changed to "0010";
var number = 7;
should be changed to "0007";
In all modern browsers you can use
numberStr.padStart(4, "0");
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
function zeroPad(num) {
return num.toString().padStart(4, "0");
}
var numbers = [1310, 120, 10, 7];
numbers.forEach(
function(num) {
var paddedNum = zeroPad(num);
console.log(paddedNum);
}
);
function pad_with_zeroes(number, length) {
var my_string = '' + number;
while (my_string.length < length) {
my_string = '0' + my_string;
}
return my_string;
}
try these:
('0000' + number).slice(-4);
or
(number+'').padStart(4,'0');
Here's another way. Comes from something I did that needs to be done thousands of times on a page load. It's pretty CPU efficient to hard code a string of zeroes one time, and chop as many as you need for the pad as many times as needed. I do really like the power of 10 method -- that's pretty flexible.
Anyway, this is as efficient as I could come up with:
For the original question, CHOOSE ONE of the cases...
var number = 1310;
var number = 120;
var number = 10;
var number = 7;
then
// only needs to happen once
var zeroString = "00000";
// one assignment gets the padded number
var paddedNum = zeroString.substring((number + "").length, 4) + bareNum;
//output
alert("The padded number string is: " + paddedNum);
Of course you still need to validate the input. Because this ONLY works reliably under the following conditions:
Number of zeroes in the zeroString is desired_length + 1
Number of digits in your starting number is less than or equal to your desired length
Backstory:
I have a case that needs a fixed length (14 digit) zero-padded number. I wanted to see how basic I could make this. It's run tens of thousands of times on a page load, so efficiency matters. It's not quite re-usable as-is, and it's a bit inelegant. Except that it is very very simple.
For desired n digits padded string, this method requires a string of (at least) n+1 zeroes. Index 0 is the first character in the string, which won't ever be used, so really, it could be anything.
Note also that string.substring() is different from string.substr()!
var bareNum = 42 + '';
var zeroString = "000000000000000";
var paddedNum = zeroString.substring(bareNumber.length, 14) + bareNum
This pulls zeroes from zeroString starting at the position matching the length of the string, and continues to get zeroes to the necessary length of 14. As long as that "14" in the third line is a lower integer than the number of characters in zeroString, it will work.
function pad(n, len) {
return (new Array(len + 1).join('0') + n).slice(-len);
}
might not work in old IE versions.
//to: 0 - to left, 1 - to right
String.prototype.pad = function(_char, len, to) {
if (!this || !_char || this.length >= len) {
return this;
}
to = to || 0;
var ret = this;
var max = (len - this.length)/_char.length + 1;
while (--max) {
ret = (to) ? ret + _char : _char + ret;
}
return ret;
};
Usage:
someString.pad(neededChars, neededLength)
Example:
'332'.pad('0', 6); //'000332'
'332'.pad('0', 6, 1); //'332000'
An approach I like is to add 10^N to the number, where N is the number of zeros you want. Treat the resultant number as a string and slice off the zeroth digit. Of course, you'll want to be careful if your input number might be larger than your pad length, but it's still much faster than the loop method:
// You want to pad four places:
>>> var N = Math.pow(10, 4)
>>> var number = 1310
>>> number < N ? ("" + (N + number)).slice(1) : "" + number
"1310"
>>> var number = 120
>>> number < N ? ("" + (N + number)).slice(1) : "" + number
"0120"
>>> var number = 10
>>> number < N ? ("" + (N + number)).slice(1) : "" + number
"0010"
…
etc. You can make this into a function easily enough:
/**
* Pad a number with leading zeros to "pad" places:
*
* #param number: The number to pad
* #param pad: The maximum number of leading zeros
*/
function padNumber(number, pad) {
var N = Math.pow(10, pad);
return number < N ? ("" + (N + number)).slice(1) : "" + number
}
I wrote a general function for this. It takes an input control and pad length as input.
function padLeft(input, padLength) {
var num = $("#" + input).val();
$("#" + input).val(('0'.repeat(padLength) + num).slice(-padLength));
}
With RegExp/JavaScript:
var number = 7;
number = ('0000'+number).match(/\d{4}$/);
console.log(number);
With Function/RegExp/JavaScript:
var number = 7;
function padFix(n) {
return ('0000'+n).match(/\d{4}$/);
}
console.log(padFix(number));
No loop, no functions
let n = "" + 100;
let x = ("0000000000" + n).substring(n.length);//add your amount of zeros
alert(x + "-" + x.length);
Nate as the best way I found, it's just way too long to read. So I provide you with 3 simples solutions.
1. So here's my simplification of Nate's answer.
//number = 42
"0000".substring(number.toString().length, 4) + number;
2. Here's a solution that make it more reusable by using a function that takes the number and the desired length in parameters.
function pad_with_zeroes(number, len) {
var zeroes = "0".repeat(len);
return zeroes.substring(number.toString().length, len) + number;
}
// Usage: pad_with_zeroes(42,4);
// Returns "0042"
3. Here's a third solution, extending the Number prototype.
Number.prototype.toStringMinLen = function(len) {
var zeroes = "0".repeat(len);
return zeroes.substring(self.toString().length, len) + self;
}
//Usage: tmp=42; tmp.toStringMinLen(4)
Use String.JS librairy function padLeft:
S('123').padLeft(5, '0').s --> 00123