I'm writing a javascript program that needs random 10-digit numbers which can sometimes have the 10th digit as 0. I assigned a variable to one of these numbers and then logged it to make sure everything was alright...but it wasn't. Here is my code:
var candidate = 0135740250;
var candidate2 = 0272189318;
console.log(candidate); // Returns 24625320
console.log(candidate2); // Returns 272189318
I tried taking the 0 off the beginning of candidate, and that made it return correctly, but I don't understand why it doesn't work in the first place. I included candidate2 above because whatever I do to it, adding 0s in the middle, changing it in other ways, it stays correct, so I can't figure out why candidate is being screwed up. I vaguely understand the number storage system in Javascript and that its not perfect, but I need a predictable, repeatable way to return the correct number.
The question is: what is happening here and how can I reliably avoid it?
"The question is: what is happening here..."
The first is a valid octal, so it gets converted as such.
The second is not a valid octal because of the 8 and 9, so it gets the base 10 representation with the leading 0 removed since it adds no value.
"...and how can I reliably avoid it?"
Avoiding it will depend on how you're generating your numbers. If you were using .random() it wouldn't be an issue, so I'd assume they're coming from some sort of string representation.
If so, and if you're using parseInt() to get the actual number, then pass it 10 as the second argument to ensure base-10 representation.
JavaScript treats any number beginning with 0 as octal if it is a valid octal.
Another quack is, if you know the length of string to generate
"use strict"
var strlent = 10
console.log(candidate2.toString().length < strlent ? "0" +
candidate2.toString() : candidate2.toString())
>>>0272189318
Related
I am using a function where large integers are passed as a parameter.
For example.
doSomethingWithInteger(1234567890)
However, it's a little difficult to keep track of the place value of integer (and thus its value), if I do something like this:
doSomethingWithInteger(101934109348)
How many digits, and thus what is the actual value of that integer really? It's hard to keep track. Obviously the following example blows up with an error because it's interpreted as multiple arguments:
doSomethingWithInteger(101 934 109 348)
But is there a way to achieve some effect like that in JS to make the amount of digits, and thus the value of the integer more clear?
Edit: To clarify, I'm having trouble keeping track of the value of the numbers by not being able to track the place values, and not having trouble determining the length of the string.
There's no solution built in to the syntax but I suppose you could do something this with a function.
function toInt(arr) {
return parseInt(arr.join(''));
}
toInt([123, 456, 7890]); // 1234567890
doSomethingWithInteger(toInt([101, 934, 109, 348]));
This works by taking in an array, combining the entire array into a single string, then casting that string to an integer. Obviously you'll incur a performance hit with this.
Do you want to know the number of digits that has the int?
You can get it by doing this:
(12324897928).toString().length
I read some other's code, there is some piece of code below. I am wondering What does the method do with num?
formatNumber: function (num, digit) {
var pow = Math.pow(10, digit || 5);
return Math.round(num * pow) / pow;
}
BTW when I running
formatNum(11.267898, 5), it gave me 11.2679, is this OK?
Essentially, the function returns the number with certain precision. The precision is digit, which is 5 if not provided.
The return part essentially brings that many values (equal to digit) decimal right to left and then discard the rest and finally divides again to get the original value reduces to precision of digit.
Regarding BTW edit -
The value obtained is correct. See details below
When you call formatNum(11.267898, 5), you're asking the number to round to 5 digit precision and your number has 6 digit precision - precision is digits after the dot.
Now when you call num * pow the number becomes 1126789.8 and when you round this number, it rounds to closest integer which is 11.26790. Finally when you divide it by pow (100000), the number becomes 11.2679, discarding last 0 as trailing Zero in precision is pointless.
That is a really poor piece of code.
First, the naming conventions don't match what the code does at all.
The function name formatNumber() suggests that it formats a number. In other words, it ought to produce a string representation of a number, formatted in some way. But the function doesn't do this, it returns another number. That makes no sense. Numbers don't have a format, they are just numbers.
The parameter name digit sounds like it would contain a single digit. But it doesn't. It contains a count of digits that you want to round the number to. When you name things, singular and plural matter!
It gets worse.
As you found, the function doesn't even work. In your example, formatNum(11.267898,5) returns the number 11.2679. Why did it give you four digits when you asked for five? The result you were expecting was 11.26790, wasn't it? Well, of course that is identical to 11.2679, if we're talking about numbers. But what good does that do you when you wanted five digits?
Or to take a ridiculously simple example: formatNumber(1,2). You might expect that to produce 1.00, but it produces 1. Of course that is really the same value, but not formatted the way you want.
Now we go from the ridiculous to the sublime.
JavaScript has always had a built-in function that does exactly what we would expect formatNumber() to do: number.toFixed(digits). This does proper rounding and always returns the number of digits after the decimal point that you ask for. And of course, to be able to do that, it returns a string, not a number.
If we try these examples using .toFixed() they work as expected:
(11.267898).toFixed(5) returns the string "11.26790".
(1).toFixed(2) returns "1.00".
And so on, for just about anything you can throw at it. (It gives up on numbers with magnitude too large and uses exponential notation instead.)
Note that the parentheses around the first number in those examples are just needed to avoid a syntax error; in most cases you'd be using a variable and they would not be required, e.g.
myNumber.toFixed(2)
To summarize, not only does formatNumber() not do what it says and not anything useful, it was never needed in the first place!
parseInt(123123123123123123123123); //return 1
parseInt(123123123123123123123123123); //return 1
parseInt(123123123123123123123123123123);//return 1
Test in chrome!
A little creative reading of the documentation for parseInt() provides an answer for this. Here's what's happening:
parseInt expects its first argument to be a string. If it isn't, it converts it to a string. This is actually hilarious, because it appears to do that by...wrapping it in quotes and passing it through .toString(), which is more or less the converse of parseInt() in this case. In your example, parseInt(123123123123123123123123); becomes parseInt("1.2312312312312312e+29").
THEN it takes the converted-to-string value and passes it through parseInt(). As the documentation tells us, if it encounters a non-numeric character, it aborts and goes with what it has so far...and it truncates to an integer. So it's taking "1.2312312312312312e+29", reaching the +, aborting, parsing "1.2312312312312312" instead, and coming up with 1.
Unintended consequences!
You'll only see this problem with ints large enough that when converted to strings, they render in exponential notation. The underlying problem is that even though you'd think parseInt() and Number.toString() would mirror each other...they don't, quite, because int values passed through toString() can generate strings that parseInt() doesn't understand.
First, always specify the radix (second parameter) to avoid guessing.
Second, parseInt expects a string, so add quotes around your number.
parseInt("123123123123123123123123123123", 10)
1.2312312312312312e+29
Mozilla developer reference has good documentation of this function and examples. Regarding the radix, they say:
Always specify this parameter to eliminate reader confusion and to guarantee predictable behavior. Different implementations produce different results when a radix is not specified.
What I am trying to do is make an EV Track for Pokemon, you do not need to know what that is. Basically I want to add, for example, 3 into the attack input box, and 2 into defense and click submit, then 3 should appear in the grid under attack, and 2 under defense. Then if I put 1 in the attack input box, it should add 1 to the display in the grid.
But right now, instead of adding the numbers like numbers, it treats them as strings, and only adds them to the attack display.
Here is my code
http://pastebin.com/xy8232nG
Sorry if I do something wrong related ot the format of my question, just let me know, I'll fix it
So I added that parseint thing, and it works fine until I change the number or add 2 to attack and 2 to hp or something like that, it gives me "NaN" instead of a number
edit: so only the attack and special attack displays work, and if i input a value into any other stat, the special attack and attack values change to "NaN"
First off, you wrote defD as defF in your code by accident.
But more importantly, you are mixing strings and numbers. In Javascript, innerHTML returns a string. A string can be any piece of text, like "I am a jelly donut". It returns a string because innerHTML is capable of carrying more than numbers - it could contain text too. So innerHTML returns a string, just to be safe.
As such, you are trying to add a number to a string (piece of text) and you can't add a number to a sentence. So Javascript decides to treat the number like another piece of text rather than a number, and simply tacks the second number on the end of the first one rather than doing a mathematical equation.
Now many others have been saying "use parseInt, use parseInt!" and normally, that would work. That is because parseInt is a function that takes strings and converts them to numbers. However, when you start out, some of your textboxes are empty, so parseInt does not know what to do. So you get NaN (or, "Not a Number" to be exact) because the box is blank.
Usually, I avoid using parseInt because it is a function and in general, using plain math works faster and better than using a function in JS. An easy workaround to your problem is to to multiply the strings by one. Now, I know what you're thinking. "But if adding a number to text doesn't work, why does multiplying?" Simple. You cannot multiply text. As such, Javascript is forced to think of it like two numbers, rather than two strings.
atk += document.getElementById('atk').value*1;
spa += document.getElementById('spa').value*1;
def += document.getElementById('def').value*1;
spd += document.getElementById('spd').value*1;
hp += document.getElementById('hp').value*1;
spe += document.getElementById('spe').value*1;
document.getElementById("atkD").innerHTML = atk;
document.getElementById("spaD").innerHTML = spa;
document.getElementById("defD").innerHTML = def;
document.getElementById("spdD").innerHTML = spd;
document.getElementById("hpD").innerHTML = hp;
document.getElementById("speD").innerHTML = spe;
An added bonus is that this won't return NaN like parseInt does. Try it in your code and see.
(Note: you might want to use a for loop to loop through those and shorten your code instead. It isn't really necessary, but it would look nicer in your code.)
Use the parseInt function to make the values integers. Example:
.....
atk += parseInt(document.getElementById('atk').value);
.....
I have an interesting question, I have been doing some work with javascript and a database ID came out as "3494793310847464221", now this is being entered into javascript as a number yet it is using the number as a different value, both when output to an alert and when being passed to another javascript function.
Here is some example code to show the error to its fullest.
<html><head><script language="javascript">alert( 3494793310847464221);
var rar = 3494793310847464221;
alert(rar);
</script></head></html>
This has completly baffeled me and for once google is not my friend...
btw the number is 179 more then the number there...
Your number is larger than the maximum allowed integer value in javascript (2^53). This has previously been covered by What is JavaScript's highest integer value that a Number can go to without losing precision?
In JavaScript, all numbers (even integral ones) are stored as IEEE-754 floating-point numbers. However, FPs have limited "precision" (see the Wikipedia article for more info), so your number isn't able to be represented exactly.
You will need to either store your number as a string or use some other "bignum" approach (unfortunately, I don't know of any JS bignum libraries off the top of my head).
Edit: After doing a little digging, it doesn't seem as if there's been a lot of work done in the way of JavaScript bignum libraries. In fact, the only bignum implementation of any kind that I was able to find is Edward Martin's JavaScript High Precision Calculator.
Use a string instead.
179 more is one way to look at it. Another way is, after the first 16 digits, any further digit is 0. I don't know the details, but it looks like your variable only stores up to 16 digits.
That number exceeds (2^31)-1, and that's the problem; javascript uses 32-bit signed integers (meaning, a range from –2,147,483,648 to 2,147,483,647). Your best choice is to use strings, and create functions to manipulate the strings as numbers.
I wouldn't be all too surprised, if there already was a library that does what you need.
One possible solution is to use a BigInt library such as: http://www.leemon.com/crypto/BigInt.html
This will allow you to store integers of arbitrary precision, but it will not be as fast as standard arithmetic.
Since it's to big to be stored as int, it's converted to float. In JavaScript ther is no explicit integer and float types, there's only universal Number type.
"Can't increment and decrement a string easily..."
Really?
function incr_num(x) {
var lastdigit=Number(x.charAt(x.length-1));
if (lastdigit!=9) return (x.substring(0,x.length-1))+""+(lastdigit+1);
if (x=="9") return "10";
return incr_num(x.substring(0,x.length-1))+"0";
}
function decr_num(x) {
if(x=="0") return "(error: cannot decrement zero)";
var lastdigit=Number(x.charAt(x.length-1));
if (lastdigit!=0) return (x.substring(0,x.length-1))+""+(lastdigit-1);
if (x=="10") return "9"; // delete this line if you like leading zero
return decr_num(x.substring(0,x.length-1))+"9";
}
Just guessing, but perhaps the number is stored as a floating type, and the difference might be because of some rounding error. If that is the case it might work correctly if you use another interpreter (browser, or whatever you are running it in)