我有一个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是一个值得讨论的案例。
答案 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
参数以f
或F
转换说明符的样式转换。
和
的文字表示无穷大的double参数将转换为
[-]inf
或[-]infinity
样式之一-该样式是实现定义的。表示NaN的双参数将转换为样式[-]nan
或[-]nan(n-char-sequence)
中的一种-该样式以及任何n-char序列的含义都是实现定义的。 F转换说明符分别产生INF
,INFINITY
或NAN
而不是inf
,infinity
或nan
。277)>
即Java中最安全的方法是尝试解析双精度型,如果失败,则将String
小写并测试-
的存在作为第一个字符,并使用{{1 }}和.startsWith("nan")
如果您需要支持不符合标准的Windows C运行时,这当然无济于事。
答案 2 :(得分:0)
一个可能更通用的选择是将浮点数在写入redis时转换为十六进制,然后在读取时转换回十六进制。通过将其转换为十进制字符串,可以确保不会有任何精度损失,而且还可以涵盖+/- Inf和NaN情况。
这是可能的,因为双方都使用IEEE浮点数。