Каков приемлемый способ отправки 64-битных значений через JSON? - PullRequest
23 голосов
/ 16 октября 2008

Некоторые из моих данных являются 64-битными целыми числами. Я хотел бы отправить их в программу JavaScript, работающую на странице.

Однако, насколько я могу судить, целые числа в большинстве реализаций JavaScript являются 32-разрядными знаковыми величинами.

Кажется, у меня есть два варианта:

  1. Отправьте значения в виде строк
  2. Отправка значений в виде 64-битных чисел с плавающей запятой

Опция (1) не идеальна, но вариант (2) кажется гораздо менее совершенным (потеря данных).

Как вы справились с этой ситуацией?

Ответы [ 5 ]

21 голосов
/ 16 октября 2008

Кажется, это меньше проблема с JSON и больше проблема с самим Javascript. Что вы планируете делать с этими цифрами? Если это просто волшебный токен, который вам нужно позже вернуть на сайт, во что бы то ни стало, просто используйте строку, содержащую значение. Если вам действительно нужно выполнить арифметику со значением, вы можете написать свои собственные подпрограммы Javascript для 64-битной арифметики.

Одним из способов представления значений в Javascript (и, следовательно, в JSON) было бы разделение чисел на два 32-битных значения, например.

  [ 12345678, 12345678 ]

Чтобы разбить 64-битное значение на два 32-битных значения, сделайте что-то вроде этого:

  output_values[0] = (input_value >> 32) & 0xffffffff;
  output_values[1] = input_value & 0xffffffff;

Затем рекомбинировать два 32-битных значения в 64-битное значение:

  input_value = ((int64_t) output_values[0]) << 32) | output_values[1];
7 голосов
/ 25 января 2016

На самом деле существует ограничение на уровне точности JavaScript / ECMAScript до 53 бит для целых чисел (они хранятся в мантиссе «двойного» 8-байтового буфера памяти). Поэтому передача больших чисел в формате JSON не будет сериализована, как ожидается клиентом JavaScript, который урезает их до 53-битного разрешения.

> parseInt("10765432100123456789")
10765432100123458000

См. Number.MAX_SAFE_INTEGER константа и Number.isSafeInteger() функция:

Константа MAX_SAFE_INTEGER имеет значение 9007199254740991. обоснование этого числа заключается в том, что JavaScript использует двойную точность Числа в формате с плавающей запятой, как указано в IEEE 754 и могут только безопасно представлять числа между -(2^53 - 1) и 2^53 - 1.

Безопасный в этом контексте относится к способности представлять целые числа точно и правильно их сравнить. Например, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 будет оцените true, что математически неверно. Увидеть Number.isSafeInteger() для получения дополнительной информации.

Из-за разрешения числа с плавающей точкой в ​​JavaScript использование "64-битных чисел с плавающей точкой", как вы предлагали, будет иметь те же ограничения.

ИМХО лучшим вариантом является передача таких значений в виде текста. Это будет все еще отлично читаемый контент JSON, и с ним будет легко работать на уровне JavaScript.

Представление «чистая строка» - это то, что указывает OData для его Edm.Int64 или Edm.Decimal типов .

В этом случае API-интерфейс Twitter добавляет в JSON определенное поле ".._str":, например:

{
   "id": 10765432100123456789,           // for JSON compliant clients
   "id_str": "10765432100123456789",     // for JavaScript
    ...
}

Мне очень нравится этот параметр, так как он по-прежнему совместим с клиентами, поддерживающими int64. На практике такой дублированный контент в JSON не сильно повредит, если его дефлировать / сжать на уровне HTTP.

После передачи в виде строки вы можете использовать библиотеки, такие как strint - библиотека JavaScript для строковых кодированных целых чисел для обработки таких значений.

6 голосов
/ 13 мая 2009

Тип чисел Javascript (64-битный IEEE 754) имеет точность около 53 бит.

Но если вам не нужно добавлять или умножать символы, вы можете оставить 64-битное значение в виде 4-символьной строки, поскольку JavaScript использует UTF-16.

Например, 1 может быть закодировано как "\ u0000 \ u0000 \ u0001". Преимущество заключается в том, что сравнение значений (==,>, <) работает со строками, как и ожидалось. Также кажется простым записать битовые операции: </p>

function and64(a,b) {
    var r = "";
    for (var i = 0; i < 4; i++)
        r += String.fromCharCode(a.charCodeAt(i) & b.charCodeAt(i));
    return r;
}
2 голосов
/ 17 октября 2008

Представление числа JS является стандартным ieee double, поэтому вы не можете представить 64-битное целое число. В iirc вы можете получить, возможно, 48 бит фактической точности int в два раза, но все битопы JS снижают до 32-битной точности (это то, чего требует спецификация. ууу!), поэтому, если вам действительно нужно 64-битное int в js, вам нужно реализовать свой собственный 64-битная логическая библиотека int.

0 голосов
/ 16 октября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...