I gave an example of using .tofixed() with math, functions, and arrays, to a beginner coder friend who has been reviewing these topics in his class.
const bananaX = 9;
const bananaY = 2.9768;
bananaArray = [bananaX , bananaY];
console.log("X before array = " + bananaX);
console.log("Y before array = " + bananaY + '\n')
console.log("X,Y after array = " + bananaArray + '\n')
console.log("Value of X in array: " + bananaArray[0]+ '\n')
console.log("Value of Y in array: " + bananaArray[1]+ '\n')
function bananaDivision (bananaArray){
console.log("Value of X after function = " + bananaX);
console.log("Value of Y after function = " + bananaY + '\n')
let bananaDivided = Math.abs(bananaX/bananaY );
console.log (`X divided by Y = + ${bananaDivided}` + '\n')
let bananaFixed = bananaDivided.toFixed(2);
console.log("After using .toFixed(2) : " + bananaFixed + '\n');
};
bananaDivision();
They were understanding and following along no problem.
Then they asked me - "What if we put a decimal in the .toFixed ?"
So I ran:
const bananaX = 9;
const bananaY = 2.9768;
bananaArray = [bananaX , bananaY];
console.log("X before array = " + bananaX);
console.log("Y before array = " + bananaY + '\n')
console.log("X,Y after array = " + bananaArray + '\n')
console.log("Value of X in array: " + bananaArray[0]+ '\n')
console.log("Value of Y in array: " + bananaArray[1]+ '\n')
function bananaDivision (bananaArray){
console.log("Value of X after function = " + bananaX);
console.log("Value of Y after function = " + bananaY + '\n')
let bananaDivided = Math.abs(bananaX/bananaY );
console.log (`X divided by Y = + ${bananaDivided}` + '\n')
let bananaFixed = bananaDivided.toFixed(2);
let bananaFixed1 = bananaDivided.toFixed(.69420);
let bananaFixed2 = bananaDivided.toFixed(1.69420);
console.log("After using .toFixed(2) : " + bananaFixed + '\n');
console.log("After using .toFixed(.69420) : " + bananaFixed1 + '\n');
console.log("After using .toFixed(1.69420) : " + bananaFixed2 + '\n');
};
bananaDivision();
I explained it as that .toFixed is looking at the first number within the () and that the decimals are ignored.
Am I correct? For my own curiousity, is there a crazy way to break .toFixed() so that it actually uses decimals? I'm experimenting atm but wanted to know if someone already figured that out.
I explained it as that .toFixed is looking at the first number within the () and that the decimals are ignored.
This would be correct. That is essentially what happens.
For full correctness, the input of toFixed() will be converted to an integer. The specification states that the argument must first be converted to a number - NaN will be converted to a zero. Numbers with a fractional part will be rounded down.
Which means that if you pass any number, you essentially get the integer part of it.
It also means that non-numbers can be used:
const n = 3;
console.log(n.toFixed("1e1")); // 1e1 scientific notation for 10
You're close, since toFixed() expects an integer it will handle converting decimal numbers before doing anything else. It uses toIntegerOrInfinity() to do that, which itself uses floor() so the number is always rounded down.
Most of Javascript handles type conversion implicitly, so it's something you should really understand well if you don't want to run into problems. There's a free book series that explains that concept and a lot of other important Javascript knowledge very well, it's called You Don't Know JS Yet.
just a demo how .tofixed works !!!!!!
function roundFloat(x, digits) {
const arr = x.toString().split(".")
if (arr.length < 2) {
return x
}else if(arr[1] === ""){
return arr[0]
}else if(digits < 1){
return arr[0]
}
const st = parseInt(x.toString().split(".")[1]);
let add = false;
const rudgt = digits
const fX = parseInt(st.toString().split("")[rudgt]);
fX > 5 ? add = true : add = false
nFloat = parseInt(st.toString().split("").slice(0, rudgt).join(""))
if (add) {
nFloat += 1
}
const repeat0 = (() => {
if (rudgt - st.toString().length < 0) {
return 0
}
return rudgt - st.toString().length
})()
const output = x.toString().split(".")[0] + "." + nFloat.toString() + "0".repeat(repeat0);
return output
}
console.log(roundFloat(1.200, 2))
This is my first JavaScript project, so I'm sure this code isn't pretty, and could be written in a much better way, but that aside, I've encountered a problem I just don't understand. I'm sure it's just a bug I've made myself, but I just simply can't find it.
The '>' (greater than) operator works fine on numbers over 100, but stops working when it gets to 100. For some reason 100 > 99 returns false?
https://jsbin.com/vigocu/edit?console,output
Move the slider to the right, and then slowly to the left, and you will see it returning "true" until it reaches 100. From there it returns "false"
function getSliderInput(inputSliderId) {
var backSwingArray = [100];
var downSwingArray = [];
document.querySelector('#' + inputSliderId).addEventListener('input', fillArray , false);
function fillArray() {
if (isNaN(downSwingArray[downSwingArray.length - 1]) && backSwingArray[backSwingArray.length - 1] < this.value) {
backSwingArray.push(this.value);
} else if (downSwingArray[downSwingArray.length - 1] > this.value || isNaN(downSwingArray[downSwingArray.length - 1])){
console.log('Is ' + downSwingArray[downSwingArray.length - 1] + ' > ' + this.value + ' return ' + (downSwingArray[downSwingArray.length - 1] > this.value));
downSwingArray.push(this.value);
} else {
console.log('Is ' + downSwingArray[downSwingArray.length - 1] + ' > ' + this.value + ' return ' + (downSwingArray[downSwingArray.length - 1] > this.value));
return;
}
}
}
value on input elements is always a string. While that won't be a problem initially, when you're comparing this.value to the 100 you've put in the array to start with, you then push this.value into the array as-is (as a string). That means later, you'll end up comparing that stored string with another this.value value, which is also a string. If either operand to > is a number, it will coerce the other operand to number (the way + does, see below), but if both operands are strings, it will do a lexical comparison, not a numeric one, and "100" is indeed < "99" because "1" is < "9".
So you want to convert this.value to a number early on, and then use that number both when comparing and when pushing into your array. You have many ways to do that:
The unary + will require the entire string to be a valid number, but will treat "" as 0; it will also treat strings starting with 0x as hexadecimal
var num = +this.value;
// or perhaps
var num = this.value === "" ? NaN : +this.value;
// or even
var str = this.value.trim(); // .trim can be shimmed on obsolete browsers
var num = str === "" ? NaN : +str;
parseInt(..., 10) (the 10 is specifying the radix [number base] to use) will allow garbage at the end of the string, treat "" as NaN, and treat any string prefixed with 0x as 0 (since it stops at the first invalid character)
var num = parseInt(this.value, 10);
Number(...) does what + does
var num = Number(this.value); // or variations above on +
I have this code:
var theNumber = Number(prompt("Pick a number", ""));
alert("Your number is the sum of " + theNumber + 10);
I notice that Javascript tries to convert the 10 into a string (as expected) and I was wondering what should I change within my code for the output the be the actual sum of the value theNumber(that the user will choose) plus the number 10.
Parentheses.
You need to do:
alert("Your number is the sum of " + (theNumber + 10));
The issue is that it works from left to right, so it sees a string and then converts theNumber to a string and then it sees the 10 and converts the 10 to a string. By adding parentheses, you can get it to do the addition first, and then convert into a string.
var theNumber = Number(prompt("Pick a number", ""));
alert("Your number is the sum of " + (theNumber + 10));
Preceding the alert with the transformation to a number (JavaScript Number() Function) will fill theNumber with what is indeed a number:
var theNumber = Number(prompt("Pick a number", ""));
alert(theNumber + 10 + " sums to your number");
alert("Your number is the sum of " + (theNumber + parseInt(10)));
The parseInt() function parses a string and returns an integer.
today I stumbled on a strange (in my opinion) case in JavaScript. I passed a non-hexadecimal string to the parseInt function with the base of 16 and...I got the result.
I would expect the function to throw some kind of exception or at least return NaN, but it succeeded parsing it and returned an int.
My call was:
var parsed = parseInt('dsff66', 16); // note the 's' in the first argument
document.write(parsed);
and the result was: 13.
I noticed that it "stops" parsing with the first character that doesn't belong to the numeral system specified in the 2nd argument, so calling parseInt('fg',16) I would get 15 as a result.
In my opinion, it should return NaN. Can anyone explain to me why it doesn't? Why would anyone want this function to behave like this (return an integer even if it isn't the precise representation of the string passed) ?
parseInt reads input until it encounters an invalid character, and then uses whatever valid input it read prior to that invalid character. Consider:
parseInt("17days", 10);
This will use the input 17 and omit everything after the invalid d.
From the ECMAScript specification:
If [input string] S contains any character that is not a radix-R digit, then let Z [the string to be integer-ified] be the substring of S consisting of all characters before the first such character; otherwise, let Z be S.
In your example, s is an invalid base-16 character, so parseInt uses only the leading d.
As for why this behavior was included: there's no way to know for sure, but this is quite likely an attempt to reproduce the behavior of strtol (string to long) from C's standard library. From the strtol(3) man page:
...the string is converted to a long int value in the obvious manner, stopping at the first character which is not a valid digit in the given base.
This connection is further supported (to some degree) by the fact that both parseInt and strtol are specified to ignore leading whitespace, and they can both accept a leading 0x for hexadecimal values.
Why would anyone want this function to behave like this (return an integer even if it isn't the precise representation of the string passed)?
Because most of the time (by far) you're working with base 10 numbers, and in that case JS can just cast - not parse - the string to a number. (edit: Apparently not just base-10; see update below.)
Since JS is dynamically typed, some strings work just fine as numbers without any work on your part. For instance:
"21" / 3; // => 7
"12.4" / 4; // => 3.1
No need for parseInt there, because "21" and "12.4" are essentially numbers already. If, however the string was "12.4xyz" then you would indeed get NaN when dividing, since that is decidedly not a number and can't be implicitly cast or coerced to one.
You can also explicitly "cast" a string to number with Number(someString). While it too only supports base 10, it will indeed return NaN for invalid strings.
So because JS already has implicit and explicit type casting/conversion/coercion, parseInt's role isn't to be a yet another type casting function.
parseInt's role is instead to be, well, a parsing function. A function that tries its best to make sense of its input, returning what it can. It's for when you have a string you can't just cast because it's not quite perfectly numeric. (And, like JS's basic syntax, it's reminiscent of C, as apsillers' answer explained nicely.)
And since it's a parser, not a casting function, it's got the additional feature of being able to handle other bases than 10.
Now, you might ask why there isn't a strict casting function that handles non-base-10 numbers, and would complain like you want, but... hey, there just isn't. JS's designers just decided that parseInt would suffice, because, again, 0x63 percent of the time, you're dealing with base 10.
Closest you can get to "casting" is probably something horribly hacky like:
var hexString = "dsff66";
var number = eval("0x" + hexString); // attempt to interpret as a hexadecimal literal
which'll throw a SyntaxError because 0xdsff66 isn't a valid hex literal.
Update: As Lekensteyn points out in the comments, JS appears to properly cast 0x-prefixed hexadecimal strings too. I didn't know this, but indeed this seems to work:
1 * "0xd0ff66"; // => 13696870
1 * "0xdsff66"; // => NaN
which makes it the simplest way to cast a hex string to a number - and get NaN if it can't be properly represented.
Same behavior applies to Number(), e.g Number("0xd0ff66") returns an integer, and Number("0xdsff66") returns NaN.
(/update)
Alternatively, you can check the string beforehand and return NaN if needed:
function hexToNumber(string) {
if( !/^(0x)?[0-9a-f]+$/i.test(string) ) return Number.NaN;
return parseInt(string, 16);
}
In this particular case parseInt() interpret letter from "A" to "F" as hexadecimal and parse those to decimal numbers. That means d will return 13.
What parseInt() does
parseInt("string", radix) interpret numbers and letters in the string as hexadecimal (it depend on the radix) to number.
parseInt() only parse number or letter as hexadecimal from the beginning of the string until invalid character as hexadecimal.
If parseInt() can't find any number or letter as hexadecimal at the beginning of the string parseInt() will return NaN.
If the radix is not defined, the radix is 10.
If the string begin with "0x", the radix is 16.
If the radix defined 0, the radix is 10.
If the radix is 1, parseInt() return NaN.
If the radix is 2, parseInt() only parse "0" and "1".
If the radix is 3 , parseInt() only parse "0", "1", and "2". And so on.
parseInt() parse "0" to 0 if there is no number follows it as the result and remove 0 if there is number follows it. e.g. "0" return 0 and "01" return 1.
If the radix is 11, parseInt() only parse string that begins with number from "0" to "9" and/or letter "A".
If the radix is 12, parseInt only parse string that begins with number from "0" to "9" and/or letter "A" and "B", and so on.
the maximum radix is 36, it will parse string that begins with number from "0" to "9" and/or letter from "A" to "Z".
If the characters interpreted as hexadecimal more than one, every characters will has different value, though those characters are the same character. e.g. parseInt("AA", 11) the first "A" has different value with the second "A".
Different radix will return different number though the strings is the same string.
See it in action
document.body.innerHTML = "<b>What parseInt() does</b><br>" +
"parseInt('9') = " + parseInt('9') + "<br>" +
"parseInt('0129ABZ', 0) = " + parseInt('0129ABZ', 0) + "<br>" +
"parseInt('0', 1) = " + parseInt('0', 1) + "<br>" +
"parseInt('0', 2) = " + parseInt('0', 2) + "<br>" +
"parseInt('10', 2) = " + parseInt('10', 2) + "<br>" +
"parseInt('01', 2) = " + parseInt('01', 2) + "<br>" +
"parseInt('1', 2) = " + parseInt('1', 2) + "<br>" +
"parseInt('A', 10) = " + parseInt('A', 10) + "<br>" +
"parseInt('A', 11) = " + parseInt('A', 11) + "<br>" +
"parseInt('Z', 36) = " + parseInt('Z', 36) + "<br><br>" +
"<b>The value:</b><br>" +
"parseInt('A', 11) = " + parseInt('A', 11) + "<br>" +
"parseInt('A', 12) = " + parseInt('A', 12) + "<br>" +
"parseInt('A', 13) = " + parseInt('A', 13) + "<br>" +
"parseInt('AA', 11) = " + parseInt('AA', 11) + " = 100 + 20" + "<br>" +
"parseInt('AA', 12) = " + parseInt('AA', 12) + " = 100 + 30" + "<br>" +
"parseInt('AA', 13) = " + parseInt('AA', 13) + " = 100 + 40" + "<br>" +
"parseInt('AAA', 11) = " + parseInt('AAA', 11) + " = 1000 + 300 + 30" + "<br>" +
"parseInt('AAA', 12) = " + parseInt('AAA', 12) + " = 1000 + 500 + 70" + "<br>" +
"parseInt('AAA', 13) = " + parseInt('AAA', 13) + " = 1000 + 700 + 130" + "<br>" +
"parseInt('AAA', 14) = " + parseInt('AAA', 14) + " = 1000 + 900 + 210" + "<br>" +
"parseInt('AAA', 15) = " + parseInt('AAA', 15) + " = 1000 + 1100 + 310";
For radices above 10, the letters of the alphabet indicate numerals greater than 9. For example, for hexadecimal numbers (base 16), A through F are used.
In your string dsff66, d is a hexadecimal character(even though the string is non hex) which fits the radix type and is equivalent to number 13. It stops parsing after that since next character is not hexadecimal hence the result.
Just wondering if anyone can work out why I keep getting for eg. 3+3=33 and not 6.
The rest of the coding works fine for the divide and times its the addition that keeps stuffing up and wont come up with the correct answer.. please help if you can.
here is my code:
<html>
<head>
<title>Practical Task 8 </title>
</head>
<body>
<button onclick="myFunction()">Press & Enter First Digit & Second Digit</button>
<script type="TEXT/JavaScript">
function myFunction()
{
var x=prompt("Please enter first number","0");
var y=prompt("Please enter second number","0");
var sum = x;
var sum2 = y;
var n = (x * y);
var n2 = (x / y);
var n3 = (x + y);
document.write(sum + " + " + sum2 + " = " + n3);
document.write("<BR>" + sum + " * " + sum2 + " = " + n);
document.write("<BR>" + sum + " / " + sum2 + " = " + n2);
}
</script>
</body>
</html>
You're performing string concatenation, not integer addition.
Use parseInt first:
x = parseInt( x, 10 );
y = parseInt( y, 10 );
MDN recommends always specifying the radix (the 10 part) to avoid problems, such as if a user prepends a number with 0 (where it'll be parsed as octal), or if different browsers have a different default radix (wtf, I know!).
You have to do this because the output of prompt is always a string, even if it's a number (e.g. "10" or "0123"), you need to tell JavaScript to interpret the data as a number (use parseInt if it's an integer (a whole number), or use parseFloat if you'll accept numbers with decimal places). Confusingly the + operator works for both string and number types, where it performs either concatenation (i.e. joining strings together like glue) or addition depending on the type of its operands.
Because your code is adding strings.
User input is always string.
You need to parseInt(x, 10) and parseInt(y, 10) to parse the string value into int base 10.