将NaN作为字符串输出为“ nan”的双精度值

时间:2019-02-20 23:43:09

标签: java c++ c linux

我有一个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的std::isfinite()std::isnan()进行了练习,最终可以定义自己的有效(-)NaN(-)Infinity字符串,但这似乎不像我需要重新发明标准化的NaN和Infinity字符串。由于C端输出inf,而Java想要Infinity,所以Infinity可能有些不同。

最终,我需要能够解码Java中的C ++应用程序编写的数据。 nan和inf不能像编写的那样被Java解码。我的重点是NaN,但Infinity是一个值得讨论的案例。

3 个答案:

答案 0 :(得分:1)

为什么不只在Java代码中使用类似的代码来解析双精度?

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
    }
  }
}

答案 1 :(得分:1)

Linux案例是(a)根据ISO/IEC 9899:2001的正确行为:

  

[{%e%E]

     

[...]表示无穷大或NaN的double参数以fF转换说明符的样式转换。

的文字
  

表示无穷大的double参数将转换为[-]inf[-]infinity样式之一-该样式是实现定义的。表示NaN的双参数将转换为样式[-]nan[-]nan(n-char-sequence)中的一种-该样式以及任何n-char序列的含义都是实现定义的。 F转换说明符分别产生INFINFINITYNAN而不是infinfinitynan。277)

即Java中最安全的方法是尝试解析双精度型,如果失败,则将String小写并测试-的存在作为第一个字符,并使用{{1 }}和.startsWith("nan")

如果您需要支持不符合标准的Windows C运行时,这当然无济于事。

答案 2 :(得分:0)

一个可能更通用的选择是将浮点数在写入redis时转换为十六进制,然后在读取时转换回十六进制。通过将其转换为十进制字符串,可以确保不会有任何精度损失,而且还可以涵盖+/- Inf和NaN情况。

这是可能的,因为双方都使用IEEE浮点数。