如何转换信号NaN的安静喃? [英] How to convert signalling NaN to quiet NaN?
问题描述
我要转换信号NaN的安静楠C.任何人可以提出一个方法是什么?
I want to convert signalling NaN to quiet NaN in C. Could anybody suggest a method?
感谢。
推荐答案
我想我会扩大我的意见,并提供解决方案。
I guess I'll expand on my comment and provide a solution.
在这里棘手的部分是能够读取/比较 SNAN
不触发异常。毕竟这就是所谓的信号的一个原因。 维基百科说,关于 SNAN
甚至比较操作会触发一个例外。
The tricky part here is being able to read/compare the sNaN
without triggering an exception. After all it's called "signalling" for a reason. Wikipedia says that even comparison operations on sNaN
will trigger an exception.
所以直接使用若干!=号
或 isnan(值)
可能不工作,因为他们调用比较,将引发硬件异常。 (我不完全知道如何 isnan(值)
不过是实现)。
So a direct use of number != number
or isnan(value)
probably don't work because they invoke comparisons and will trigger a hardware exception. (I'm not entirely sure how isnan(value)
is implemented though.)
编辑:校正,它看起来像 isnan()
绝不会触发一个例外,甚至在信号 NaN的
这样就使得这个答案的其余部分没有意义的。
EDIT : Correction, it looks like isnan()
will never trigger an exception even on a signalling NaN
so that makes the rest of this answer pointless.
在predicate isNaN(x)的确定值是NaN,从不
信号异常时,即使x是一个信令NaN的
The predicate isNaN(x) determines if a value is a NaN and never signals an exception, even if x is a signaling NaN.
这意味着它可以在评论完成刚才这个由Chrisoph的建议:
Meaning it can be done as just this as suggested by Chrisoph in the comments:
if(isnan(value))
value = NAN;
这里是我原来的答复,不使用 isnan(值)
:
Here's my original answer that doesn't use isnan(value)
:
所以,我能想到这样做的唯一的办法就是去按位路线。
So the only way I can think of doing this is to go the bitwise route.
假设浮动
是标准的IEEE单precision和 INT
是一个32位整数,然后这里是去了解一个方法:(请注意,我没有测试过这一点)
Assuming float
is standard IEEE single-precision and int
is a 32-bit integer, then here's one way to go about this: (Note that I haven't tested this.)
union{
int i;
float f;
} val;
val.f = // Read the value here.
// If NaN, force it to a quiet NaN.
if ((val.i & 0x7f80000) == 0x7f80000){
val.i |= 0x00400000;
}
请注意,这种方法并不完全C-标准,将调用实现定义的行为。还注意到,这种方法是不是特别有效,因为需要对FP和整数单元之间移动数据。
Note that this approach is not completely C-compliant and will invoke implementation defined behavior. Also note that this approach is not particularly efficient due to the need to move data between the FP and integer units.
下面是如何工作的:
- 工会显然是用来
浮动
的位进入一个INT
。 - 所有
的NaN
将在0x7f80000
位设定。 if语句测试将检查是否所有这些位的设置。 -
I | = 0x00400000;
强制NaN的
来一个安静的NaN的
。 22位决定了NaN的
是沉默或安静。它强制为1将使它成为一个安静的NaN的
。
- The union obviously is used to get the bits of the
float
into anint
. - All
NaNs
will have the bits in the0x7f80000
set. The if-statement test will check if all of these bits are set. i |= 0x00400000;
forces theNaN
to a quietNaN
. Bit 22 determines whether theNaN
is silent or quiet. Forcing it to 1 will make it a quietNaN
.
编辑2:如果您不能使用工会,这里的一些其他的办法(每个都有自己的缺点):
EDIT 2: If you can't use unions, here's are some other approaches (each of which have their own drawbacks):
方法1:
float f = // Read the value here.
int i = *(int*)&f;
if ((i & 0x7f80000) == 0x7f80000){
i |= 0x00400000;
}
f = *(float*)&i;
不足:它违反了严格的走样,但仍然可能会正常工作
Downside: It violates strict aliasing, but will probably still work.
方法2:
char buf[sizeof(float)];
float f = // Read the value here.
*(float*)&buf = f;
int i = *(int*)&buf;
if ((i & 0x7f80000) == 0x7f80000){
i |= 0x00400000;
}
*(int*)&buf = i;
f = *(float*)&buf;
同样的想法与工作的memcpy()
。
缺点:如果对齐问题,你需要确保 BUF
对齐
Downside: If alignment matters, you need to make sure buf
is aligned.
方法3:实施自己的 isnan()
:
请参阅这个问题:哪里是源头code对于isnan?
这篇关于如何转换信号NaN的安静喃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!