Dav*_*ven 4 math floating-point nan
我有一些在AMD64 Linux上开发的数字代码(使用LLVM 3.2).
我最近用XCode将它移植到OSX 10.9.它运行正常,但它失败了许多单元测试:似乎Linux上返回NaN(或-NaN)的一些计算现在返回OSX,-NaN(或NaN).
我能否安全地假设正负NaN是等价的并调整我的单元测试以接受成功,或者这是更严重的错误的标志?
Ste*_*non 11
在IEEE-754算术中没有"负NaN"的概念.NaN编码仍然有一个符号位,并且有一个"符号位"操作的概念,它使用或影响该位(copysign,abs,其他几个),但是当解释NaN编码时它没有任何意义作为一种价值.许多打印例程碰巧将该位打印为负号,但它在形式上毫无意义,因此标准中没有太多可以控制其值应该是什么(除了上述函数之外).
这是IEEE-754(2008)的相关部分:
将支持格式的安静NaN转换为外部字符序列将产生语言定义的"nan"或除了大小写(例如,"NaN")之外的等效序列,具有可选的前一个符号.(本标准不解释NaN的符号.)
因此,您的平台的转换函数可能会打印出NaN值的"符号",但它没有任何意义,您不应该将其视为测试目的.
编辑得更强一点:将NaN数据的"符号位"附加意义几乎总是一个错误.
这完全取决于您的单元测试正在测试什么。
您很可能能够将它们视为等效的,除非您正在进行的测试实际上是针对 IEEE754 浮点软件本身,或者是打印它们的 C 运行时代码。否则,如果使用您正在测试的代码将它们视为相同,则您应该将它们视为相同。
这是因为测试应该在任何情况下都符合您的实际使用情况。doCalc()
一个(诚然是人为的)示例是,如果您正在测试返回双精度值的函数。如果它只是这样使用过:
x = doCalc()
if x is any sort of Nan:
doSomethingWithNan()
Run Code Online (Sandbox Code Playgroud)
那么你的测试应该将所有NaN
值视为相等。但是,如果您这样使用它:
x = doCalc()
if x is +Nan:
doSomethingForPositive()
else:
if x is -Nan:
doSomethingForNegative()
Run Code Online (Sandbox Code Playgroud)
那么你就会想将它们视为不同的。
同样,如果您的实现在小数位中创建了有用的有效负载(见下文),并且您的实际代码使用了它,则也应该通过单元测试对其进行检查。
由于 NaN 只是指数中的所有 1 位和分数中的所有 0 位以外的其他内容,因此符号位可以是正数或负数,并且小数位可以是各种值。但是,它仍然是数据类型表示之外的值或结果,因此,如果您只是期望如此,那么符号或有效负载包含的内容可能没有什么区别。
在检查值的文本输出方面NaN
,NaN 上的维基百科页面表明不同的实现可能会给您带来广泛不同的输出,其中:
nan
NaN
NaN%
NAN
NaNQ
NaNS
qNaN
sNaN
1.#SNAN
1.#QNAN
-1.#IND
Run Code Online (Sandbox Code Playgroud)
甚至显示不同符号和有效负载的变体对其 NaN 性没有影响:
-NaN
NaN12345
-sNaN12300
-NaN(s1234)
Run Code Online (Sandbox Code Playgroud)
因此,如果您希望在单元测试中实现大规模可移植,您会注意到所有输出表示(除了nan
其中一个)都包含字符串的某种变体。因此,不区分大小写地搜索字符串的值nan
或ind
会将它们全部找到。这可能不适用于所有环境,但它的覆盖范围非常大。
无论如何,C 标准对于使用%f
(%F
使用大写字母) 输出浮点值有这样的规定:
表示a
double
的参数NaN
将转换为其中一种样式[-]nan
或[-]nan(n-char-sequence)
- 哪种样式以及 any 的含义n-char-sequence
是实现定义的。
因此,只需检查该值是否位于nan
其中就足够了。
归档时间: |
|
查看次数: |
1211 次 |
最近记录: |