Двойное значение, которое является выводом NaN в виде строки как «nan» - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть приложение на C / C ++, которое записывает числовые значения в redis в виде строки.У меня также есть Java-приложение, которое будет читать эти значения из redis.Иногда по уважительным причинам мы получаем значение с плавающей запятой, которое имеет значение NaN или -NaN.Однако при использовании sprintf(charPtr, "%e", dblVal); значение выводится как nan.Я также попробовал то же самое утверждение с %E, и это привело к NAN.Когда Java пытается выполнить синтаксический анализ с помощью Float.parseFloat() или Double.parseDouble, возникает исключение NumberFormatException.

Это приложение было перенесено из Solaris в Linux, а затем прошло через некоторые обновления Linux, и в какой-то момент «NaN» стало «nan»».Я не могу точно сказать, в каком обновлении в конечном итоге появилось это поведение.

Я прошел упражнение, используя cmath's std::isfinite() и std::isnan(), и в конечном итоге могу определить свой собственный действительный (-)NaN или (-)Infinityстроки, но это не похоже, что мне нужно заново изобретать нормализованные строки NaN и Infinity.Бесконечность может немного отличаться, так как сторона C выводит inf, но Java хочет Infinity.

В конечном итоге мне нужно иметь возможность декодировать данные, написанные приложением C ++ в Java.Nan и Inf не могут быть декодированы Java как написано.Я сфокусировался на NaN, но Infinity - это тот случай, который должен быть раскрыт.

Ответы [ 3 ]

0 голосов
/ 21 февраля 2019

В случае Linux (а) правильное поведение соответствует ИСО / МЭК 9899: 2001 :

[%e, %E]

[...] Аргумент double, представляющий бесконечность или NaN, преобразуется в стиле спецификатора преобразования f или F.

и текст для

Двойной аргумент, представляющий бесконечность, преобразуется в один из стилей [-]inf или [-]infinity - этот стиль определяется реализацией,Двойной аргумент, представляющий NaN, преобразуется в один из стилей [-]nan или [-]nan(n-char-sequence) - стиль и значение любой n-символьной последовательности определяются реализацией.Спецификатор преобразования F выдает INF, INFINITY или NAN вместо inf, infinity или nan, соответственно, 277)

Т.е. самый безопасный в Javaбыло бы попытаться проанализировать двойное число, и если это не удалось, строчные буквы String и проверить наличие - в качестве первого символа и остатка после возможного знака с .startsWith("nan") и .startsWith("inf")

Конечно, это не поможет, если вам нужно поддерживать нестандартные среды выполнения Windows C.

0 голосов
/ 22 февраля 2019

Потенциально более универсальным вариантом будет преобразование числа с плавающей запятой в шестнадцатеричное при записи в redis, а затем обратное преобразование при чтении.Это обеспечит отсутствие потери точности при преобразовании его в десятичную строку, но также охватит случаи +/- Inf и NaN.

Это возможно, поскольку обе стороны используют IEEE с плавающей запятойчисло.

0 голосов
/ 21 февраля 2019

Почему бы просто не использовать что-то подобное в своем Java-коде для разбора типа double?

double parseDouble(String s) throws NumberFormatException {
  try {
    return Double.valueOf(s);
  } catch (NumberFormatException e) {
    if (s.equalsIgnoreCase("nan")) {
      return Double.NaN;
    } else if (s.equalsIgnoreCase("inf") || s.equalsIgnoreCase("+inf")) {
      return Double.POSITIVE_INFINITY;
    } else if (s.equalsIgnoreCase("-inf")) {
      return Double.NEGATIVE_INFINITY;
    } else {
      throw e; // Invalid string
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...