What's the function of the "|" (pipe) operator? [duplicate] - javascript

This question already has answers here:
Using bitwise OR 0 to floor a number
(7 answers)
Closed 8 years ago.
I have this line that I copied from another place:
Total += parseFloat($(this).val())|0;
What's the function of the operator |? When I change the number, I get different results.

The | in JavaScript is an integer bitwise OR operator. In that context, it strips off any fractional portion returned by parseFloat. The expression parseFloat($(this).val()) will result in a number with (potentially) a fractional component, but then |0 will convert it to an integer number, OR it with 0 (which means it won't change), and so the overall result is to get a whole number.
So functionally, it truncates the fractional portion off the number. -1.5 becomes -1, and 1.5 becomes 1. This is like Math.floor, but truncating rather than rounding "down" (Math.floor(-1.5) is -2 — the next lowest whole number — rather than -1 as the |0 version gives us).
So perhaps that's why it was used, to chop off (rather than "floor") the fractional portion of the number.
Alternately, it could be a typo. The author of that code might have meant to write this (note || rather than |):
Total += parseFloat($(this).val()) || 0;
That defends against the possibility that $(this).val() returns "" or similar, resulting in parseFloat returning NaN. It uses the curiously-powerful || operator to return 0 rather than NaN in that case. (And there's an advertisement for putting spaces around your operators.) Would have to know the context of the code to say whether truncating to a whole number (|) makes sense when adding to Total, or if they were just defending the NaN case.

The | operator in javascript is the bitwise or operator
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Bitwise_Operators
This operator treats the operands as 32 bit integers and for every bit returns 1 if either is 1 and 0 otherwise.

Related

is there a difference between these two snippets of code and if yes what is it?

function addBinary(a,b) {
let sum= a+b
if (sum<0){
sum=0xffffffff+sum+1
}
return parseInt(sum).toString(2)
}
and especially the logic of how 0xffffffff has been used to achieve same result
function decimalToBinary(decimal){
return (decimal >>> 0).toString(2);
}
function addBinary(a,b) {
return decimalToBinary(a+b);
}
The >>> operator always interprets the given number as an unsigned 32 bit number. When the second operand is 0, nothing changes to that and the result is unsigned.
So for instance, -1 in binary is 0xffffffff in signed 32-bit, where the most significant bit (at the left) is the sign bit. But because exceptionally the >>> does not interpret that as a sign bit, it actually is seen as a positive number, i.e. 0xffffffff. Compared to the original -1 that is 0x100000000 more! This is always the difference for negative inputs. For -2 you'll get 0xfffffffe, for -3 you'll get 0xfffffffd, ...etc.
The first function emulates this. If sum is negative, we must do something, as the other function (using >>>) will never return a negative number.
The idea is to add that 0x100000000 difference. In fact, the author of this function was prudent, and evidently didn't want to work with numbers that exceed the 32 bit range, so 0x100000000 was off the board (it uses 33 bits). But one can split the job into parts. We can add one less (0xffffffff) to the sum, and then add the remaining 1. This is just a theoretical game though. In JavaScript there is no problem in adding 0x100000000, so they could just as well have done that. In other languages however, those that use 32 bit numbers, it would be necessary to first add 0xffffffff and only then 1.

javascript outcome of toFixed().length

I have question about ".toFixed().length. I have here a if statement: if (num.toFixed(2).length > 4) {". And i dont understand the outcome of the result.
i thougth it woud count the length of the string. Because toFixed covert the number to a string. But i dont get the outcome. I hope you have a ans because i cant find it on the internet or my teachers ad school dont know it ether.
Thank you for your time,
num = 1234.567
>>> 1234.567
num2 = num.toFixed(2).length
>>> 7 // why is this 7??
num2
>>> 7
num = 1234
>>> 1234
num2 = num.toFixed(2).length
>>> 7
num = 2
>>> 2
num2 = num.toFixed(2).length
>>> 4// and this 4??
What you describe in your question is essentially the expected behavior of toFixed().
It will always round the passed number to two decimals and convert it to a string always showing these two decimals, even if they're 0.
You can try several more results in this small sample on ideone.
Back to your initial question:
if (num.toFixed(2).length > 4)
This expression could be translated to "string representation is longer than 4 characters".
Since we already mentioned the two decimals and the decimal point always being there, all string results will end in .## (where # could be any digit). That's a string length of 3 characters.
This essentially means there have to be at least two more characters before the decimal point for this statement to become true:
#.## would be 4 characters, which still doesn't fulfill the condition.
'##.##' works. These are 5 characters, which is definitely longer than 4.
So this means any number equal to or bigger than 10 would fulfill this statement. Considering there's rounding involved, any number greater than 9.95 should work for this.
So why not write if (num > 9.95)? Simply because that's only part of the answer.
There are negative numbers as well. If you evaluate Number(-1).toFixed(2) you'll get the string -1.00, which is 5 characters already!
But what about rounding? Here it gets even more interesting. If you run Number(-.01).toFixed(2) one would assume that this is rounded to 0.00. This is kinda true, but JavaScript will retain the negative prefix, resulting in -0.00. This is once again a string with 5 characters!
So combining these two observations we can say that the expression in your if() clause is true under either of these two conditions:
The number is bigger than 9.5 (i.e. it's rounded to 10 or larger)
The number is negative.
So one could replace the rather cryptic/complicated expression with the following term and get the same results:
if (num < 0 || num >= 9.5)
num = 1234.567
>>> 1234.567
num2 = num.toFixed(2).length
>>> 7 // why is this 7??
Here you want to know the length of the string so it's giving you the string length. If you do .tofixed(2) on 1234.567 it will remain the same.

Why does string to number comparison work in Javascript

I am trying to compare a value coming from a HTML text field with integers. And it works as expected.
Condition is -
x >= 1 && x <= 999;
Where x is the value of text field. Condition returns true whenever value is between 1-999 (inclusive), else false.
Problem is, that the value coming from the text field is of string type and I'm comparing it with integer types. Is it okay to have this comparison like this or should I use parseInt() to convert x to integer ?
Because JavaScript defines >= and <= (and several other operators) in a way that allows them to coerce their operands to different types. It's just part of the definition of the operator.
In the case of <, >, <=, and >=, the gory details are laid out in §11.8.5 of the specification. The short version is: If both operands are strings (after having been coerced from objects, if necessary), it does a string comparison. Otherwise, it coerces the operands to numbers and does a numeric comparison.
Consequently, you get fun results, like that "90" > "100" (both are strings, it's a string comparison) but "90" < 100 (one of them is a number, it's a numeric comparison). :-)
Is it okay to have this comparison like this or should I use parseInt() to convert x to integer ?
That's a matter of opinion. Some people think it's totally fine to rely on the implicit coercion; others think it isn't. There are some objective arguments. For instance, suppose you relied on implicit conversion and it was fine because you had those numeric constants, but later you were comparing x to another value you got from an input field. Now you're comparing strings, but the code looks the same. But again, it's a matter of opinion and you should make your own choice.
If you do decide to explicitly convert to numbers first, parseInt may or may not be what you want, and it doesn't do the same thing as the implicit conversion. Here's a rundown of options:
parseInt(str[, radix]) - Converts as much of the beginning of the string as it can into a whole (integer) number, ignoring extra characters at the end. So parseInt("10x") is 10; the x is ignored. Supports an optional radix (number base) argument, so parseInt("15", 16) is 21 (15 in hex). If there's no radix, assumes decimal unless the string starts with 0x (or 0X), in which case it skips those and assumes hex. Does not look for the new 0b (binary) or 0o (new style octal) prefixes; both of those parse as 0. (Some browsers used to treat strings starting with 0 as octal; that behavior was never specified, and was [specifically disallowed][2] in the ES5 specification.) Returns NaN if no parseable digits are found.
Number.parseInt(str[, radix]) - Exactly the same function as parseInt above. (Literally, Number.parseInt === parseInt is true.)
parseFloat(str) - Like parseInt, but does floating-point numbers and only supports decimal. Again extra characters on the string are ignored, so parseFloat("10.5x") is 10.5 (the x is ignored). As only decimal is supported, parseFloat("0x15") is 0 (because parsing ends at the x). Returns NaN if no parseable digits are found.
Number.parseFloat(str) - Exactly the same function as parseFloat above.
Unary +, e.g. +str - (E.g., implicit conversion) Converts the entire string to a number using floating point and JavaScript's standard number notation (just digits and a decimal point = decimal; 0x prefix = hex; 0b = binary [ES2015+]; 0o prefix = octal [ES2015+]; some implementations extend it to treat a leading 0 as octal, but not in strict mode). +"10x" is NaN because the x is not ignored. +"10" is 10, +"10.5" is 10.5, +"0x15" is 21, +"0o10" is 8 [ES2015+], +"0b101" is 5 [ES2015+]. Has a gotcha: +"" is 0, not NaN as you might expect.
Number(str) - Exactly like implicit conversion (e.g., like the unary + above), but slower on some implementations. (Not that it's likely to matter.)
Bitwise OR with zero, e.g. str|0 - Implicit conversion, like +str, but then it also converts the number to a 32-bit integer (and converts NaN to 0 if the string cannot be converted to a valid number).
So if it's okay that extra bits on the string are ignored, parseInt or parseFloat are fine. parseInt is quite handy for specifying radix. Unary + is useful for ensuring the entire string is considered. Takes your choice. :-)
For what it's worth, I tend to use this function:
const parseNumber = (str) => str ? +str : NaN;
(Or a variant that trims whitespace.) Note how it handles the issue with +"" being 0.
And finally: If you're converting to number and want to know whether the result is NaN, you might be tempted to do if (convertedValue === NaN). But that won't work, because as Rick points out below, comparisons involving NaN are always false. Instead, it's if (isNaN(convertedValue)).
The MDN's docs on Comparision states that the operands are converted to a common type before comparing (with the operator you're using):
The more commonly used abstract comparison (e.g. ==) converts the operands to the same Type before making the comparison. For relational abstract comparisons (e.g., <=), the operands are first converted to primitives, then to the same type, before comparison.
You'd only need to apply parseInt() if you were using a strict comparision, that does not perform the auto casting before comparing.
You should use parseInt if the var is a string. Add = to compare datatype value:
parseInt(x) >== 1 && parseInt(x) <== 999;

Why parseInt() doesn't convert "true" to number, while multiplying does? [duplicate]

This question already has answers here:
parseInt vs unary plus, when to use which?
(6 answers)
Closed 8 years ago.
I started from expression returning true (I choose 1==1) and wrote it in console
cosole.log(1==1);
It logs true. Now I want to convert it to integer (1) and wrap it in parseInt()
console.log(parseInt(1==1));
It logs NaN. Looks like it is trying to convert 1==1 to string before it converts it to number.
Then I'll simply multiply 1==1 by 1.
console.log((1==1)*1);
It logs 1.
Why in first case it converts it converts true to string before converting it to integer (resulting NaN) while I want to convert it to string and in the second case it converts true directly to integer? I'd expect that true*1 will be NaN too.
parseInt, by virtue of being a “parse”r, should take a string and produce an integer, so it converts its argument to a string. *, because it’s multiplication, converts its arguments to numbers.
If you want to convert anything to an (32-bit) integer, | 0 works; it’s a 32-bit bitwise integer operation, and can’t result in NaN, because that’s not a 32-bit integer.
Just to emphasize that parseInt is a wholly inappropriate way of casting anything but a string to an integer: what does this give you?
parseInt(5000000000000000000000000)
(For numbers that big, use Math.round(x), or Math.round(+x) if you like to be explicit.)
parseInt(bool) == NaN
parseInt(bool*1) == parseInt(int) == int
I believe Javascript makes true = 1 and false = 0 when you multiply it.
EDIT: to further this, parseInt(bool*bool) would also work

JavaScript | operator [duplicate]

This question already has answers here:
Using bitwise OR 0 to floor a number
(7 answers)
Closed 8 years ago.
Anyone able to explain what "|" and the value after does? I know the output for 0 creates sets of 13, the numbers, 3, 2, 1, 0. But what about | 1, or | 2.
var i = 52;
while(i--) {
alert(i/13 | 0);
}
It is the bitwise OR operator. There is both an explanation and an example over at MDC. Since doing bitwise OR with one operand being 0 produces the value of the other operand, in this case it does exactly nothing rounds the result of the division down.
If it were written | 1 what it would do is always print odd numbers (because it would set the 1-bit to on); specifically, it would cause even numbers to be incremented by 1 while leaving odd numbers untouched.
Update: As the commenters correctly state, the bitwise operator causes both operands to be treated as integers, therefore removing any fraction of the division result. I stand corrected.
This is a clever way of accomplishing the same effect as:
Math.floor(i/13);
JavaScript developers seem to be good at these kinds of things :)
In JavaScript, all numbers are floating point. There is no integer type. So even when you do:
var i = 1;
i is really the floating point number 1.0. So if you just did i/13, you'd end up with a fractional portion of it, and the output would be 3.846... for example.
When using the bitwise or operator in JavaScript, the runtime has to convert the operands to 32 bit integers before it can proceed. Doing this chops away the fractional part, leaving you with just an integer left behind. Bitwise or of zero is a no op (well, a no op in a language that has true integers) but has the side effect of flooring in JavaScript.
It's a bitwise operator. Specifically the OR Bitwise Operator.
What it basically does is use your var as an array of bits and each corresponding bit is with eachother. The result is 1 if any of them is 1. And 0 if both are 0.
Example:
24 = 11000
10 = 1010
The two aren't of equal length so we pad with 0's
24 = 11000
10 = 01010
26 = 11010
24 | 10 = 26
Best way to learn this is to readup on it.
That is the bitwise OR. In evaluating the expression, the LHS is truncated to an integer and returned, so | is effecively the same as Math.floor().

Categories

Resources