c - 使用 float 和比较作为错误代码是否可移植?

标签 c floating-point comparison portability

我计划使用特殊的浮点值从函数返回错误代码,例如可以用 IEEE-754 表示的 99.75f:

float myFunction(void)
{
    /* Do some stuff */
    if(error) return 99.75f;
}

稍后检查该值,如下所示:

float result = myFunction();
if(result == 99.75f) printf("Error !");

假设我的编译器符合 C90 或 C99 标准,该解决方案是否可移植?它可以在任何平台上运行吗? 或者编译器是否允许执行一些魔术或一些优化,将浮点转换为 double ,更改其表示形式等,这可能会破坏相等性检查?

著名的What Every Computer Scientist Should Know About Floating-Point Arithmetic似乎没有涵盖这种情况(特定于C)。 与 FLT_EPSILON 或 ULP 进行比较是无关紧要的,因为我确实想检查 float 的表示...

最佳答案

C 标准对浮点行为没有太多保证。它确实说:

All floating constants of the same source form shall convert to the same internal format with the same value.

这意味着99.75f将产生相同的值,无论它是什么,无论它出现在程序中的什么位置。它不保证 99.750f 将转换为相同的值,因此您必须确保每次出现时都使用完全相同的源文本。它也不保证其他源文本(例如 99.76f)不会转换为相同的值。因此,您需要确保您使用的特殊值与计算中出现的任何值完全分开。

C 标准不保证浮点系统的基数是 2 或 10。因此,仅依靠该标准,您无法确定 99.75 是否可以表示。当然,您不太可能遇到使用基数 3 的实现。

C 标准允许实现以额外的范围和精度计算表达式。然而,一旦 99.75f 转换为浮点,仅仅给它额外的范围和精度不会改变它。 +-*/ 和库例程等操作可以产生近似结果,但是,大概,您没有在此值上进行操作。

C 标准似乎暗示浮点类型仅使用一个基数,至少对于普通浮点类型来说是这样,因为它仅定义 FLT_RADIX 来报告用于浮点类型的基数-point 系统,但定义了 FLT_MANT_DIGDBL_MANT_DIG 来报告 floatdouble 有效数中使用的位数。因此,您不必担心从 float 转换为 double 或扩展精度时 99.75 会发生变化。它只能用相同基数中的更多数字来表示,而不是转换为新的基数,因此额外的数字将为零。 (当然,缩小转换可能会改变它,因此您需要根据 float 定义特殊值,这样它只会变得更宽。)

总的来说,我希望你在这方面相当安全。然而,这并不一定是好的设计。当然,特殊值应该在源文本中仅指定一次,通过使用预处理器宏或定义为常量值的标识符。

关于c - 使用 float 和比较作为错误代码是否可移植?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48917087/

相关文章:

c++ - 如何打印 Linux 下 C++ 程序中调用的函数?

c - 如何解决错误 C2059 : syntax error : '__asm' in Visual C++ 2010 Express

c++ - 如果实数可以用 double 表示,我如何编写返回 true 的 C++ 函数?

Javascript 检查松散比较(错误值除外)

c - 目标文件夹修改后的 POSIX seekdir() 和 telldir() 行为

c - 将 child 的标准输出传递给 parent 标准输入

java.lang.ClassCastException : java. lang.Float 无法转换为 java.lang.String

c - 与 GCC 的关联数学

Python Pandas 如果 B 列中的值 = 等于 [X, Y, Z] 将 A 列替换为 "T"

php - 如何比较两个数组的相似性?