Подтвердить что ты не робот

Каков приемлемый способ отправки 64-битных значений через JSON?

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

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

Мои две опции выглядят следующим образом:

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

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

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

4b9b3361

Ответ 1

Кажется, это проблема с 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];

Ответ 2

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

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

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

function and64(a,b) {
    var r = "";
    for (var i = 0; i < 4; i++)
        r += String.fromCharCode(a.charCodeAt(i) & b.charCodeAt(i));
    return r;
}

Ответ 3

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

> parseInt("10765432100123456789")
10765432100123458000

Смотрите Number.MAX_SAFE_INTEGER constant и 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-битных чисел с плавающей запятой", как вы предложили, будет иметь те же ограничения.

IMHO лучшим вариантом является передача таких значений, как текст. Это будет по-прежнему прекрасно читаемый контент JSON и будет легко работать с уровнем JavaScript.

"Чистая строка" представляет собой представление OData для его типов Edm.Int64 или Edm.Decimal.

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

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

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

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

Ответ 4

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

Ответ 5

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