Согласно справке 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
, мы избегаем неопределенного поведения из-за несоответствия спецификатора формата и данныхвведите без изменения результата.