How does ~~ work as math.floor? [duplicate] - javascript

This question already has answers here:
What does ~~ ("double tilde") do in Javascript?
(12 answers)
`Math.trunc` vs `|0` vs `<<0` vs `>>0` vs `&-1` vs `^0`
(2 answers)
Closed 8 years ago.
I understand that ~ is a bitwise NOT operator, but how does inverting the bits on a number twice make it function as Math.floor
What does ~~ ("double tilde") do in Javascript? describes the differences between using Math.floor vs bitwise operations to round numbers in Javascript, but I am interested in how exactly inverting the bits twice accomplishes this.
Thanks

~ forces the operand to get cast to an integer. It's a trick to work around the fact that Javascript has no direct way of casting between floating point and integer values. In fact, Javascript doesn't officially have an integer-only type, but implementations are likely to use integers internally for performance.
So ~x is the bitwise inverse of castToInt(x). Then you inverse the bits again to get just castToInt(x).
It happens that casting floating point numbers to integer behaves almost like Math.floor. The most notable difference is that casting rounds towards zero, while Math.floor rounds towards negative infinity. There are some other differences as well:
js> ~~(-4.5)
-4
js> Math.floor(-4.5)
-5
js> ~~Infinity
0
js> Math.floor(Infinity)
Infinity
js> ~~NaN
0
js> Math.floor(NaN)
NaN
js> Math.floor(1e12)
1000000000000
js> ~~1e12
-727379968 // <- be aware of integer overflows!

From the spec, Bitwise NOT, ~
Let expr be the result of evaluating UnaryExpression.
Let oldValue be ToInt32(GetValue(expr)).
Return the result of applying bitwise complement to oldValue. The result is a signed 32-bit integer.
Definition of ToInt32 here.
The "complement" of a 32-bit integer i is i XOR 0xFFFFFFFF.
So put this all together and you have ~~i as meaning
ToInt32(i) XOR 0xFFFFFFFF XOR 0xFFFFFFFF
// same as
ToInt32(i) XOR 0x00000000
// same as
ToInt32(i)
Keep in mind the differences in rounding direction for negative numbers.
Personally I prefer using x | 0 over ~~x because it involves fewer operations for the same result.

It's essentially the equivalent of a truncate function (in the sense that it is casting the float into an integer, which does exactly that), which JavaScript does not have. This is why for negative numbers the behavior is actually closer to Math.ceil.

Related

XOR operator in javascript different from XOR operator in python

I am trying to replicate some javascript code into python, and for some reason the XOR operator (^) in javascript gives me a different value than the XOR operator (^) in python. I have an example below. I know the values should be different because of Math.random(), but why is it like 4 significant digits longer?
Javascript:
console.log(Math.floor(2147483648 * Math.random()) ^ 1560268851466)
= 1596700165
Python:
import math
math.floor(2147483648 * random.random()) ^ 1560268851466
= 1559124407072
Your Python result is correct, given XOR's input bits. Your longer operand is on the order of 2^40, and so is your final result.
The Javascript result has been truncated to 32 bits, the shorter operand.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators:
Bitwise operators treat their operands as a sequence of 32 bits (zeroes and ones), rather than as decimal, hexadecimal, or octal numbers. For example, the decimal number nine has a binary representation of 1001. Bitwise operators perform their operations on such binary representations, but they return standard JavaScript numerical values.
However the particular code you are using can be "fixed" via XOR-ing the 32-bit part of your number, and simply adding the rest:
// 1560268851466 = 0x16B_4745490A
console.log( (Math.floor(2147483648 * Math.random()) ^ 0x4745490A) + 0x16B00000000);
(As 2147483648 is 0x8000000, the random part is "fine", it does not get truncated)

parseInt returning values that differs by 1 [duplicate]

This question already has answers here:
What is JavaScript's highest integer value that a number can go to without losing precision?
(21 answers)
Closed 7 years ago.
I have data like this:
var currentValue="12345678901234561";
and I'm trying to parse it:
var number = parseInt(currentValue, 10) || 0;
and my result is:
number = 12345678901234560
now lets try:
currentValue="12345678901234567"
in this case parseInt(currentValue,10) will result in 12345678901234568
Can anyone explain me why parseInt is adding/substracting 1 from values provided by me?
Can anyone explain me why parseInt is adding/substracting 1 from values provided by me?
It's not, quite, but JavaScript numbers are IEEE-754 double-precision binary floating point (even when you're using parseInt), which have only about 15 digits of precision. Your number is 17 digits long, so precision suffers, and the lowest-order digits get spongy.
The maximum reliable integer value is 9,007,199,254,740,991, which is available from the property Number.MAX_SAFE_INTEGER on modern JavaScript engines. (Similarly, there's Number.MIN_SAFE_INTEGER, which is -9,007,199,254,740,991.)
Some integer-specific operations, like the bitwise operators ~, &, and |, convert their floating-point number operands to signed 32-bit integers, which gives us a much smaller range: -231 (-2,147,483,648) through 231-1 (2,147,483,647). Others, like <<, >>, and >>>, convert it to an unsigned 32-bit integer, giving us the range 0 through 4,294,967,295. Finally, just to round out our integer discussion, the length of an array is always a number within the unsigned 32-bit integer range.

Why a positive number operated with bitwise or 0 not always positive in Javascript

Why a positive number operated with bitwise or 0 not always positive in Javascript
For example:
3391700000|0
-903267296
4260919000|0
-34048296
2884900000|0
-1410067296
I'm using chrome 64-bit on Linux
related to: https://stackoverflow.com/a/12837315/1620210
Because JavaScript uses 32bit integers at most, but keep in mind every number is kind of a float in this language
If you want to truncate them to an unsigned 32bit value:
(3391700000|0) >>> 0
In JavaScript, the operands of bitwise operators are converted to signed 32-bit integers in 2's complement format. Thats why you got some loss of data and the truncated values are sometimes negative because of signed two's complement representation.
You can refer to Why bitwise shift with 0 in JavaScript yields weird results in some cases thread which was asked by myself some time ago and some answers pointed out the possible issue with bitwise operators where your operands exceed 32-bit integers very comprehensively.

Javascript 32 bit numbers and the operators & and >>>

I am trying to understand Javascript logical operators and came across 2 statements with seeminlgy similar functionality and trying to understand the difference. So, What's the difference between these 2 lines of code in Javascript?
For a number x,
x >>>= 0;
x &= 0x7fffffff;
If I understand it correctly, they both should give unsigned 32 bit output. However, for same negative value of x (i.e. most significant bit always 1 in both case), I get different outputs, what am I missing?
Thanks
To truncate a number to 32 bits, the simplest and most common method is to use the "|" bit-wise operator:
x |= 0;
JavaScript always considers the result of any 32-bit computation to be negative if the highest bit (bit 31) is set. Don't let that bother you. And don't clear bit 31 in an attempt to make it positive; that incorrectly alters the value.
To convert a negative 32-bit number as a positive value (a value in the range 0 to 4294967295), you can do this:
x = x < 0? x + 0x100000000 : x;
By adding a 33-bit value, automatic sign-extension of bit 31 is inhibited. However, the result is now outside the signed 32-bit range.
Another (tidier) solution is to use the unsigned right-shift operator with a zero shift count:
x >>>= 0;
Technically, all JavaScript numbers are 64-bit floating-point values, but in reality, as long as you keep numbers within the signed 32-bit range, you make it possible for JavaScript runtimes to optimize your code using 32-bit integer operations.
Be aware that when you convert a negative 32-bit value to a positive value using either of above methods, you have essentially produced a 33-bit value, which may defeat any 32-bit optimizations your JavaScript engine uses.

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