C语言 如何确定w/o转换,一个给定的浮动常数可以表示?



如何确定w/o转换,一个给定的浮动常数可以表示?

示例代码:

#define FLOATING_CONSTANT1  2147483647.0f
#define FLOATING_CONSTANT2  2147483520.0f
bool b1 = FLOATING_CONSTANT_CAN_BE_REPRESENTED( FLOATING_CONSTANT1 );  // false
bool b2 = FLOATING_CONSTANT_CAN_BE_REPRESENTED( FLOATING_CONSTANT2 );  // true


#define str(s) #s
#define xstr(s) str(s)
#define FLOATING_CONSTANT_CAN_BE_REPRESENTED(fc1) float_const_test(xstr(fc1), fc1)
bool float_const_test(const char *s, float f1) {
printf("<%s> %gn", s, f1);
char *endptr;
errno = 0;
double d2 = strtod(s, &endptr);
if (s == endptr) return false;
if (strcmp(endptr, "f") && strcmp(endptr, "F")) return false;
if (f1 != d2) return false;
// Note a 100% here, the string may have rounded to a double.
return true;
}
int main(void) {
puts("Good");
printf("%dn", FLOATING_CONSTANT_CAN_BE_REPRESENTED(1.5f));
printf("%dn", FLOATING_CONSTANT_CAN_BE_REPRESENTED(0x1.5p0f));
puts("nBad");
printf("%dn", FLOATING_CONSTANT_CAN_BE_REPRESENTED(1.23f));
printf("%dn", FLOATING_CONSTANT_CAN_BE_REPRESENTED(1.23e40f));
}

输出
Good
<1.5f> 1.5
1
<0x1.5p0f> 1.3125
1
Bad
<1.23f> 1.23
0
<1.23e40f> inf
0

指出:

如果FP常数的小数部分不以50结尾,则不能精确地转换为float/double

当需要精确的FP常量时,第一步是考虑十六进制浮点常量,例如0x1.23CDp12f

这可能不是您想要的答案,它可能看起来很滑稽,但在我自己的工作中,我几乎可以想象我有这个宏可供我使用。它有一个方便的优点,在floatdoublelong double操作数上都能很好地工作:

#define fp_is_exact(f) 0

但是我承认我很少写像

这样的东西
if(fp_is_exact(x))
do something the easy way;
else
do something the hard way;

无论如何,我将不得不编写代码来完成困难的方法,以及"容易的"方法。代码很少被使用,我不妨改掉想象它可能对任何事情都有用的习惯。

严肃地说:假定浮点数从来都不是精确的。准确性不是它们用来的。任何你需要表示为浮点变量的东西都不是一个确切已知的量,尤其是你在现实世界中测量的东西,比如距离,重量,速度等等。(我最喜欢的例子:从洛杉矶到纽约有多远?在英寸?)


附录:我不得不承认,有时候假设浮点数是精确的是合适的。像if(f == 0)if(f == 1)if(f == 3)这样的比较在实践中是完全没问题的。我会毫不犹豫地将精确相等的浮点变量与小于10或小于100的整数进行比较,如果是小于100,也可能是0.5。但是对于我可能想到的任何其他数字,或者我可能在C程序中操作的浮点变量,它完全可以表示为floatdouble的可能性几乎是微乎其微的。

如何确定w/o转换,一个给定的浮动常数可以表示?

编译器接受的浮动常量类型为float,double,long double或C语义上的扩展浮动类型。表示

但我认为问题的意思是,出现在源代码中的常量的词法十进制表达式是否与完全对应于某种选定的浮点类型的可表示的浮点值。我非常自信地说,这样的决定不能由预处理器做出,因为预处理器处理(预处理器)令牌的单位。虽然在某些情况下它通过将文本转换为数字来操作,但预处理器没有可访问的机制将令牌分解成更小的部分。

但是,可以在编译时对感兴趣的标记进行字符串化,并在运行时分析结果字符串表示形式。原则上也可以编写一个独立的工具或调整现有的独立预处理器来执行您想要的测试。

甚至可以想象,编译器可能会提供一个选项来警告不能精确表示的词法浮点数,这在另一个问题中已经考虑过了。(剧透:这不是编译器编写者历来认为值得实现的替代方案。)

相关内容

最新更新