我已经做了一个函数[cc],它能够在一定程度上逼近函数,这个函数给出了5个小数的精确结果(12345×6XXXXXXXXXXX,其中X位置只是舍入误差/垃圾)。
为了避免将错误扩展到使用g
结果的其他计算中,我只想将所有x位置设置为0,更好的是,将第5个小数点后的所有位置都设置为0。
在X87和SSE文献中,我还没有找到让我按照自己的意愿使用IEEE754位或它们的表示的任何东西。
有一个老的对X87的g
指令的引用,它显然是用FISTP
在SSE世界中镜像的,其优点是FISTTP
不必修改控制字,因此速度更快。
我注意到FISTTP
被称为“斩波模式”,但现在在更现代的文学作品中,只是“向零舍入”或“截断”,这让我感到困惑,因为“斩波”意味着完全删除某些东西,而“向零舍入”对我来说并不一定意味着相同的东西。
我不需要四舍五入到零,在将结果存储到内存中之前,我只需要在函数中保留最多5个小数;如何在X87(标量FPU)和SSE(矢量FPU)中执行此操作?
最佳答案
正如一些人评论的那样,more early rounding doesn't help the final result be more accurate。如果你想阅读更多关于浮点比较和奇怪/错误的文章,我强烈推荐布鲁斯道森关于浮点的系列文章。以下是the one with the index
我们终于在这个系列中达到了我一直在等待的地步
为了。在this post中,我将分享
我有浮点数学知识。这里是:
[浮点]数学很难。
你不会相信这是多么巨大,巨大,令人难以置信的困难。
我的意思是,你可能会认为很难计算
芝加哥和洛杉矶将相撞,但那只是微不足道的
浮点数学。
(如果你认为最后一段是对一句关于空间的名言的复述,就可以得到额外的分数。)
如何真正实现你的坏想法:
没有任何机器指令或C标准库函数可以截断或舍入到整数以外的任何值。
注意,有些机器指令(和C函数)将adouble
舍入到最接近的(可表示的)整数,而不将其转换为intmax_t
或任何东西,只需double
double
。所以不需要往返于固定宽度2的补码整数。
因此,要使用它们,可以按某个因子向上缩放浮动,四舍五入到最接近的整数,然后向下缩放。(就像chux基于round()
的函数,但我建议您使用C99 double rint(double)
而不是round()
。round
有奇怪的舍入语义,与x86上的任何可用舍入模式都不匹配,因此它编译成更糟糕的代码。
你一直提到的x86 asm指令没有什么特别的,不要做任何你不能要求编译器用纯C做的事情。FISTP
(Float Integer STore(并弹出x87堆栈)是编译器或asm程序员实现long lrint(double)
or (int)nearbyint(double)
.的一种方法,有些编译器可以为其中一种编写更好的代码。它使用当前的x87舍入模式(默认值:舍入到最接近的值)进行舍入,即same semantics as those ISO C standard functions。FISTTP
(带截断的浮点整数存储(并弹出x87堆栈)是part of SSE3,即使它在x87堆栈上操作。它允许编译器避免将舍入模式设置为截断(向零舍入)以实现(long)x
的C截断语义,然后恢复旧的舍入模式。
这就是“不修改控制词”的意思。这两条指令都没有,但是要在没有FISTTP的情况下实现(int)x
,编译器必须使用其他指令来修改和恢复FIST
指令周围的舍入模式。或者使用SSE2 CVTTSD2SI
在xmm寄存器中用截断来转换double,而不是传统x87堆栈上的FP值。
因为FISTTP
只在SSE3中可用,所以您只能在long double
中使用它,或者在32位代码中使用它,因为旧的32位ABI在x87堆栈上返回FP值。
另外,如果你不认识Bruce的推荐信,HHGTG:
空间很大。真的很大。你只是不相信
太大了。我的意思是你可能认为这是一个很长的路下来
通往药店的路,但那只是通往太空的花生。
关于c++ - 在用户定义的X87和SSE FPU中的点之后截断 float 和 double ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38487718/