是否有人可以方便地将ieee 754double
代码片段转换为下一个(resp.superior)float
,而不改变或假设fpu的当前舍入模式?
注意:这个约束可能意味着根本不使用fpu。在这种情况下,我想最简单的方法是在64位的长度中读取double的位,然后使用它。
为了简单起见,您可以假设您选择的是endianness,并且可以通过下面的union的d
字段使用所讨论的double:
union double_bits
{
long i;
double d;
};
我会尝试自己做,但我肯定我会介绍很难注意到错误的非规范化或负数。
最佳答案
我认为以下方法可行,但我将首先陈述我的假设:
在您的实现中,浮点数以ieee-754格式存储,
无溢出,
您有nextafterf()
可用(在c99中指定)。
而且,很可能这种方法不是很有效。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[])
{
/* Change to non-zero for superior, otherwise inferior */
int superior = 0;
/* double value to convert */
double d = 0.1;
float f;
double tmp = d;
if (argc > 1)
d = strtod(argv[1], NULL);
/* First, get an approximation of the double value */
f = d;
/* Now, convert that back to double */
tmp = f;
/* Print the numbers. %a is C99 */
printf("Double: %.20f (%a)\n", d, d);
printf("Float: %.20f (%a)\n", f, f);
printf("tmp: %.20f (%a)\n", tmp, tmp);
if (superior) {
/* If we wanted superior, and got a smaller value,
get the next value */
if (tmp < d)
f = nextafterf(f, INFINITY);
} else {
if (tmp > d)
f = nextafterf(f, -INFINITY);
}
printf("converted: %.20f (%a)\n", f, f);
return 0;
}
在我的机器上,它会打印:
Double: 0.10000000000000000555 (0x1.999999999999ap-4)
Float: 0.10000000149011611938 (0x1.99999ap-4)
tmp: 0.10000000149011611938 (0x1.99999ap-4)
converted: 0.09999999403953552246 (0x1.999998p-4)
我的想法是将
double
值转换为float
值,这个值可以小于或大于double值,具体取决于舍入模式。当转换回double
时,我们可以检查它是否小于或大于原始值。然后,如果float
的值不在正确的方向上,我们将从原始数字方向上转换的数字看下一个float
数字。