Почему число 16 конвертируется в число с плавающей точкой (6.1026988574311E_320) PHP с помощью Zend_Amf - PullRequest
3 голосов
/ 01 октября 2009

Спецификация Zend_Amf гласит, что возвращаемый из flash тип Number будет преобразован в число с плавающей точкой в ​​PHP. Хорошо. Но почему число 16 возвращается как 6.1026988574311E_320? Версия PHP 5.2.9 работает на OS X.

Я попытался принудительно привести приведение к целому числу в PHP (вышеупомянутое значение округляется до 0), а также из Actionscript с использованием int (16) - последний указывается как NULL. Как гарантировать, что Flash возвращает целое число через AMF и что PHP может с ним справиться?

Ответы [ 2 ]

6 голосов
/ 14 октября 2009

У вас классическая проблема с порядком байтов. Похоже, либо Zend, либо flash делают что-то не так с порядком байтов этого двойника. Вот программа, которая печатает double (и его шестнадцатеричное значение). Затем он обращается к порядку байтов и печатает его снова.

#include <stdio.h>
#include <stdint.h>

int main(void)
{
  double d = 16;
  uint32_t *i = (uint32_t *)(&d);
  uint8_t *c = (uint8_t *)(&d);
  size_t j;

  printf("%08x %08x %lg\n", i[1], i[0], d);

  for(j = 0; j < sizeof(double) / 2; j++)
  {
        uint8_t tmp;

        tmp = c[j];
        c[j] = c[sizeof(double) - j - 1];
        c[sizeof(double) - j - 1] = tmp;
    }

  printf("%08x %08x %lg\n", i[1], i[0], d);

  return 0;
}

На Intel (процессор с прямым порядком байтов) вы получите этот вывод

40300000 00000000 16
00000000 00003040 6.1027e-320

Возможно, вы запускаете это на PPC Mac (big endian)? Похоже, что один из ваших инструментов неправильно работает с вашей архитектурой. Отправьте сообщение об ошибке поставщикам.

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

1 голос
/ 14 октября 2009

Я не знаю полностью, что происходит в вашей ситуации, но я думаю, что смогу частично осветить то, что происходит с вашим кодом. Я провёл следующий быстрый взлом, чтобы проверить теорию:

void hexdump_double(double dbl)
{
    assert(8 == sizeof(dbl));
    printf("double: %02X %02X %02X %02X %02X %02X %02X %02X (%lg)\n",  
           ((char *)&(dbl))[0],
           ((char *)&(dbl))[1],
           ((char *)&(dbl))[2],
           ((char *)&(dbl))[3],
           ((char *)&(dbl))[4],
           ((char *)&(dbl))[5],
           ((char *)&(dbl))[6],
           ((char *)&(dbl))[7],
           dbl);
}

int main()
{
    hexdump_double(6.1026988574311E-320);
}

, который дает какой-то захватывающий результат:

double: 40 30 00 00 00 00 00 00 (6.1027e-320)

Как видите, это маленькое число с плавающей запятой - это не случайный набор битов. Тем не менее, он также не имеет отношения к «16».

Если в документации Zend_Amf указано, что тип числа ActionScript возвращается как число с плавающей точкой PHP, подразумевается class Number, задокументированный Adobe: Документация по Adobe.com Flex . Это не означает, что любое «число» будет передано как двойное число.

Int со значением меньше 2 ^ 29 будет возвращено в AMF как целочисленный тип, и я предполагаю, что Zend_Amf вернет это как целое число.

Как вы передаете объект AMF из вашего ActionScript? Возможно ли сбросить отправляемые байты?

...