Как логический сдвиг работает в JavaScript - PullRequest
0 голосов
/ 03 декабря 2018

В Javascript логический сдвиг работает иначе, чем в других языках.

var value = 1543812808507000000
var lowBits = value >>> 0

Это код JavaScript.И результат 3804366080. Но когда мы разработали эту логику в java или c, результат был 3804366016.

Какая из верных?Как работает логическое смещение в JS?

enter image description here

1 Ответ

0 голосов
/ 03 декабря 2018

Согласно справке Mozilla JS :

Константа MAX_SAFE_INTEGER имеет значение 9007199254740991 (9 007 199 254 740 991 или ~ 9 квадриллионов).Причина этого числа заключается в том, что JavaScript использует числа в формате с плавающей запятой двойной точности, как указано в IEEE 754, и может безопасно представлять только числа между - (2 53 - 1) и 2 53 * 1009.* - 1.

Как уже отмечалось в комментариях, ваш введенный номер 1543812808507000000 больше наибольшего безопасного целого числа.

Таким образом, округление происходит на стороне JavaScript.

Напротив, C и Java используют (точную) интегральную математику (ниже версии C):

unsigned long long n = 1543812808507000000ULL;
n &= 0x00000000ffffffffULL;
printf("%llu\n", n);

Альтернативный расчет:

n %= 0x0000000100000000ULL;

Таким образом, вывод C / Javaявляется математически правильным.

У вас есть большие шансы получить тот же результат в C, используя также математику с плавающей запятой:

uint64_t n64 = 1543812808507000000ULL;
double d = n64;      // on conversion, rounding occurs!
uint32_t n32 = d;    // back to 32 bit, most significant bits dropped
printf("%lu\n", (unsigned long)n32);

Для полноты: IEEE754 описывает различные алгоритмы округления, а CСтандарт не требует конкретного - фактически, он даже не предписывает IEEE754 вообще.Но так как JS и C напрямую используют одно и то же базовое оборудование (а все современное оборудование следует IEEE754 с одинаковым округлением по умолчанию), это не имеет практического значения ...

Если вам интересно узнать о приведении: uint32_t вероятно будет typedef -едным как unsigned int, но не обязательно (может быть unsigned long или даже unsigned short, все законно в соответствии со стандартом C).Для unsigned long, тем не менее, C требует, чтобы диапазон был покрыт так, что нам нужно по крайней мере 32 бита, поэтому, приведя и используя спецификатор формата %lu, мы избегаем неопределенного поведения из-за несоответствия спецификатора формата и данныхвведите без изменения результата.

...