作为一名高性能计算人员,我们倾向于尽可能默认使用单精度 float (float
或 real
)。这是因为如果每个操作单独执行得更快,您每秒可以执行更多操作。
然而,与我共事的一位资深人士始终坚持(当需要准确性时)您应该暂时将单精度数据转换为 double 据,以便执行除法。即:
float a, b;
float ans = ((double)a)/((double)b);
或
real :: a, b, ans
ans = real(dble(a)/dble(b))
取决于您使用的语言。在我看来,这看起来真的很难看,老实说,我什至不知道 ans
中的答案是否比如果您只是简单地以单点精度编写 ans = a/b
。
谁能告诉我在算术之前转换你的数字,特别是为了执行除法,是否真的会得到更准确的答案?这是一个语言/编译器特定的问题,还是由 IEEE 决定?这种准确度提高在什么数值下最为显着?
任何有启发性的评论/答案将不胜感激。
最佳答案
float ans = ((double)a)/((double)b);
这article演示 ans
始终与 IEEE 754 算术和 FLT_EVAL_METHOD=0 的单精度除法计算的结果相同。
当 FLT_EVAL_METHOD=1 时,同样的属性也同样成立。
当FLT_EVAL_METHOD=2时,我不确定。可能有人会将规则解释为 a/b
的 long double
计算必须首先四舍五入为 double
,然后为 float
。在这种情况下,它可能不如直接从 long double
舍入到 float
准确(后者产生正确舍入的结果,而前者可能在极度情况下无法这样做极少数情况,除非另一个像菲格罗亚的定理适用并表明这永远不会发生)。
长话短说,对于任何现代合理的浮点计算平台 (*),float ans = ((double)a)/((double)b);
具有迷信任何好处。你应该让你在问题中提到的资深人士展示一对 a, b
结果不同的值,更不用说更准确了。当然,如果他们坚持认为这样更好,那么提供一对值对他们来说应该没有问题,因为它会有所作为。
(*) 记得在 GCC 中使用 -fexcess-precision=standard
以保持理智
关于将单精度 float 转换为 double 以进行除法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31351631/