我计划使用特殊的浮点值从函数返回错误代码,例如可以用 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_DIG
和 DBL_MANT_DIG
来报告 float
和 double
有效数中使用的位数。因此,您不必担心从 float
转换为 double
或扩展精度时 99.75 会发生变化。它只能用相同基数中的更多数字来表示,而不是转换为新的基数,因此额外的数字将为零。 (当然,缩小转换可能会改变它,因此您需要根据 float
定义特殊值,这样它只会变得更宽。)
总的来说,我希望你在这方面相当安全。然而,这并不一定是好的设计。当然,特殊值应该在源文本中仅指定一次,通过使用预处理器宏或定义为常量值的标识符。
关于c - 使用 float 和比较作为错误代码是否可移植?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48917087/