2012-02-22 2 views
1

Рассматривая следующие примеры, это выглядит так: Math.floor(x) эквивалентно x | 0, для x >= 0. Это действительно так? Если да, то почему? (Или как x | 0 рассчитывается?)Javascript Integer Division, или Math.floor (x) эквивалентно x | 0 при х> = 0?

x = -2.9; console.log(Math.floor(x) + ", " + (x | 0)); // -3, -2 
x = -2.3; console.log(Math.floor(x) + ", " + (x | 0)); // -3, -2 
x = -2; console.log(Math.floor(x) + ", " + (x | 0)); // -2, -2 
x = -0.5; console.log(Math.floor(x) + ", " + (x | 0)); // -1, 0 
x = 0; console.log(Math.floor(x) + ", " + (x | 0)); // 0, 0 
x = 0.5; console.log(Math.floor(x) + ", " + (x | 0)); // 0, 0 
x = 2; console.log(Math.floor(x) + ", " + (x | 0)); // 2, 2 
x = 2.3; console.log(Math.floor(x) + ", " + (x | 0)); // 2, 2 
x = 2.9; console.log(Math.floor(x) + ", " + (x | 0)); // 2, 2 
x = 3.1; console.log(Math.floor(x) + ", " + (x | 0)); // 3, 3 

Это может быть полезно для выполнения целочисленного деления в Javascript: (5/3) | 0, а не Math.floor(5/3).

+1

'x> = 0' и' x Leonid

+0

Фактически, 'x | 0' также совпадает с' ~~ x', '~' является поразрядным оператором NOT, который делает это: '~ x = - (x + 1)' (добавляет 1 и изменяет знак). А так как ~ также является поразрядным оператором, он также преобразует число в целое.Повторяя ~ x, вы возвращаете исходный номер с оригинальным знаком +/-, но как целое число. Другими словами: '~~ x == (x | 0)' – DiegoDD

ответ

4

Побитовые операторы преобразуют числа в 32-разрядную последовательность. Таким образом, альтернативы, которые вы предлагаете, будут работать только с положительными подписанными 32-битными поплавками, то есть номерами от 0 до +2,147,483,647 (2^31-1).

Math.floor(2147483646.4); // 2147483647 
2147483646.4 | 0; // 2147483647 
// but… 
Math.floor(2147483648.4); // 2147483648 
2147483648.4 | 0; // -2147483648 

Еще одно отличие: если x не является числом, то результат x | 0 может быть иным, чем у Math.floor(x).

Math.floor(NaN); // NaN 
NaN | 0; // 0 

Кроме этого, результат должен быть похож на Math.floor(), до тех пор, как положительное число используется.

Вот еще несколько примеров + тесты производительности: http://jsperf.com/rounding-numbers-down

+0

Глядя на тесты производительности, похоже, что 'parseInt (x)' является самым быстрым. –

+0

@ Миша Морошко Нет, это самый медленный. Отображаемые числа - это количество операций в секунду, поэтому чем выше число, тем быстрее оно. –

+0

А ... мой плохой ... –

1

(х | 0) удаляет биты после того, таким образом мы можем получить следующий истинное отношение «»:

x | 0 = (x < 0 ? -1 : 1) * Math.floor(Math.abs(x)) ; 

х >> 0 имеет тот же эффект, что х | 0, так:

x >> 0 = x | 0 = (x < 0 ? -1 : 1) * Math.floor(Math.abs(x)) ; 
2

Вертикальная полоса является побитовым или оператором. Поскольку бит 0 равен нулю, x|0 теоретически является не-оператором. Но для его оценки операнды должны быть целыми числами, поэтому x сначала необходимо преобразовать из числа с плавающей запятой в целое число. Преобразование производится путем устранения дробной части, поэтому да, для некоторого x> = 0 имеем x|0 == Math.floor(x).

Обратите внимание, что результат зависит от размера и знака внутреннего целочисленного типа. Например, вы получите:

2147483648|0  == -2147483648  // 0x80000000 
Math.pow(2,32)|0 == 0    // the lowest 32 bits are all 0 
2

Битовые операции в JS есть 32 бита, то есть поплавок первый «слепок» в «Int».

"2.6" | 0 = 2 предполагает, что вызывается parseInt.

+0

'Math.floor' не вызывается внутри,' ToInt32' есть. См. «BitwiseORExpression» в спецификации: http://es5.github.com/x11.html#x11.10 –

+0

Вы правы. Я просто это понял. Это не имеет смысла. Потому что Math.floor () = , а не , поэтому было бы бессмысленно реализовывать его таким образом. – Candide

3

Согласно ECMAScript spec, §11.10 Бинарные Битовые операторы:

Semantics 
The production A : A @ B, where @ is one of the bitwise operators in the productions 
above, is evaluated as follows: 
1. Let lref be the result of evaluating A. 
2. Let lval be GetValue(lref). 
3. Let rref be the result of evaluating B. 
4. Let rval be GetValue(rref). 
5. Let lnum be ToInt32(lval). 
6. Let rnum be ToInt32(rval). 
7. Return the result of applying the bitwise operator @ to lnum and rnum. The result 
    is a signed 32 bit integer. 

Это как x | y рассчитывается следующим образом: x и y разбираются в Int32 а затем примените к ним оператора |.

 Смежные вопросы

  • Нет связанных вопросов^_^