@synapse_people

Почему LONG странно себя ведет?

в JAVA SE 8
0xCCD044A12FDB3E13l
равен
-3688372635733115373
а в PHP происходит каст в double
double(1.4758371437976E+19)
Почему, если ранги значений одинаковые....... и как этого можно избежать?
  • Вопрос задан
  • 203 просмотра
Решения вопроса 1
Melkij
@Melkij
PostgreSQL DBA
Рассматриваем 64 битное число, big endian byte order в hex представлении записанном как CCD044A12FDB3E13
В linux php x64 реализует целочисленный int как 64 битовое знаковое число независимо от версии интерпретатора - соответственно подходит.

Согласно синтаксису PHP шестнадцатеричная запись числа является беззнаковой, знак указывается явно. Число CC больше 7F - следовательно, в знаковом типе недостаточно разрядов (в int есть 63 разряда + бит знака, а требуется минимум 64 + знак) и число приводится к float
Если вы возьмёте 0x7cd044a12fdb3e13 - это число укладывается в 63 разряда + знак и будет помещено в int тип данных.

Если у вас машинное представление числа и его необходимо корректно разобрать - есть unpack:
var_dump(unpack('J', "\xCC\xD0\x44\xA1\x2F\xDB\x3E\x13")[1]);

Что даст искомый int(-3688372635733115373)
Плюс внимание на порядок байт. Что unpack позволяет учитывать.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
leahch
@leahch
Я мастер на все руки, я козлик Элек Мэк :-)
Потому что java строго типизированный язык и long на всех без исключения платформах имеет строго типизированную длину, причем до Java8 это еще и тип со знаком.
long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -2**63 and a maximum value of 2**63-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 2**64-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.


Ну и например можно воспользоваться коллекциями guava - https://google.github.io/guava/releases/19.0/api/d...
Ответ написан
prototype_denis
@prototype_denis
Symfony
<?php

var_dump((int) 0xCCD044A12FDB3E13); // int(-3688372635733114880)
var_dump(0xCCD044A12FDB3E13);       // float(1.4758371437976E+19)  === hexdec(...)
ini_set('precision', 25);
var_dump(0xCCD044A12FDB3E13);       // float(14758371437976436736)  === hexdec(...)

// -3688372635733115373 JAVA
// -3688372635733114880 Похапэ


¯\_(ツ)_/¯

В мусорку похапе.


Есть несеколько вещей, которые вам следует знать о типе данных long. Во-первых, это signed integer, то есть он может содержать положительные и отрицательные значения, но этот тип данных не подходит для побитовых операций. Во-вторых, long имеет разные размеры на разных платформах: на 32-битных системах он имеет размер 32 бита или 4 байта, но на 64-битных системах он может иметь размер как 4, так и 8 байт. В Unix-системах он обычно имеет размер в 8 байт, в то время как в 64-битных версиях Windows использует только 4 байта.

По этой причине вы не должны полагаться на конкретное значение типа long. Минимальное и максимальное значения, которые могут быть сохранены в типе данных long доступны в константах LONG_MIN и LONG_MAX и размер этого типа может быть определен с использованием макро SIZEOF_LONG (в отличии от sizeof(long) этот макро может быть использован и в #if директивах).

Тип данных double предназначен для хранения чисел с плавающей точкой и, обычно, следуя спецификации IEEE-754, он имеет размер в 8 байт. Детали этого формата не будут обсуждаться здесь, но вам как минимум следует знать, что этот тип имеет ограниченную точность и часто хранит не точно то значение, на которое вы рассчитываете.


https://habrahabr.ru/post/226707/

https://github.com/php/php-src/search?utf8=%E2%9C%...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Emphasoft Санкт-Петербург
от 150 000 до 300 000 ₽
Kotelov Санкт-Петербург
от 150 000 до 190 000 ₽