我有一个简单的代码:
#include <stdio.h>
int main()
{
//char d[10] = {0x13, 0x43, 0x9b, 0x64, 0x28, 0xf8, 0xff, 0x7f, 0x00, 0x00};
//long double rd = *(long double*)&d;
long double rd = 3.3621e-4932L;
printf("%Le\n", rd);
return 0;
}在我的Ubuntu x64上,它按预期打印3.362100e-4932。在我的NetBSD上,它打印1.681050e-4932
为什么会发生这种情况,我该如何解决呢?我试着用相同的结果来尝试clang和gcc。
我的系统(VM在VirtualBox 5.0中):
uname -a
NetBSD netbsd.home 7.0 NetBSD 7.0 (GENERIC.201509250726Z) amd64
gcc --version
gcc (nb2 20150115) 4.8.4
clang --version
clang version 3.6.2 (tags/RELEASE_362/final)
Target: x86_64--netbsd
Thread model: posix仅供参考
/usr/include/x86/float.h将LDBL_MIN定义为3.3621031431120935063E-4932L,此值大于printf结果。
发布于 2016-01-29 18:16:18
/usr/include/x86/float.h将LDBL_MIN定义为3.3621031431120935063E-4932L,此值大于printf结果。
LDBL_MIN是long double型的最小正归一化值。类型可以表示较小的数字,它们只是低于正常值。
我只能在NetBSD上推测问题的性质,但主要有两种可能性:
printf()对于低于正常的数字,或者至少对这个数字来说是错误的。打印的数字是您预期值的一半,这一事实表明long double表示中的(二进制)指数存在问题。考虑到IEEE对低于法线数的格式的细节,很容易想象一个printf()实现如果没有预期到低于正常数的值,就会错误地解释(二进制)指数字段来表示比实际表示的值少一个指数,因此打印的值是预期值的一半。这将是我对正在发生的事情的猜测。
您可能还可以通过打印(例如,rd * 4 )来区分错误的值和错误的显示情况。无论哪种方法,这都应该在正常数字的范围内,因此人们会假设特定于低于正常数的printf()错误不会影响打印它。
至于如何进行,您有几个选择。我最可能想到的是:
LDBL_MIN作为初始化器,而不是最接近于低于正常的long double的常量。printf()中,修复可能不会很大,而且库是开源的,就像系统的其他部分一样。https://stackoverflow.com/questions/35090322
复制相似问题