简体   繁体   English

浮点,是一个相等的比较足以防止除零?

[英]Floating Point, is an equality comparison enough to prevent division by zero?

// value will always be in the range of [0.0 - maximum]

float obtainRatio(float value, float maximum){
    if(maximum != 0.f){
        return value / maximum;  
    }else{
        return 0.f;
    }
}

The range of maximum can be anything, including negative numbers. maximum范围可以是任何值,包括负数。 The range of value can also be anything, though the function is only required to make "sense" when the input is in the range of [0.0 - maximum] . value的范围也可以是任何value ,但只有当输入在[0.0 - maximum]的范围内时才需要使用“有意义”。 The output should always be in the range of [0.0 - 1.0] 输出应始终在[0.0 - 1.0]的范围内

I have two questions that I'm wondering about, with this: 我有两个问题,我想知道,有这个:

  • Is this equality comparison enough to ensure the function never divides by zero? 这种相等比较是否足以确保函数永远不会被零除?
  • If maximum is a degenerate value (extremely small or extremely large), is there a chance the function will return a result outside of [0.0 - 1.0] (assuming value is in the right range)? 如果maximum是退化值(极小或非常大),函数是否有可能返回[0.0 - 1.0]之外的结果(假设值在正确的范围内)?

Here is a late answer clarifying some concepts in relation to the question: 这是一个迟到的答案,澄清了与该问题相关的一些概念:

Just return value / maximum 只返回值/最大值

In floating-point, division by zero is not a fatal error like integer division by zero is. 在浮点数中,除零不是像整数除零那样的致命错误。 Since you know that value is between 0.0 and maximum , the only division by zero that can occur is 0.0 / 0.0 , which is defined as producing NaN . 由于您知道该value介于0.0maximum之间,因此可以发生的唯一除零为0.0 / 0.0 ,定义为生成NaN The floating-point value NaN is a perfectly acceptable value for function obtainRatio to return, and is in fact a much better exceptional value to return than 0.0 , as your proposed version is returning. 浮点值NaN是函数obtainRatio返回的完全可接受的值,实际上是一个比0.0更好的异常值,因为您提出的版本正在返回。

Superstitions about floating-point are only superstitions 关于浮点的迷信只是迷信

There is nothing approximate about the definition of <= between floats . 关于浮点数之间<=的定义没有任何近似值 a <= b does not sometimes evaluate to true when a is just a little above b . a略高于b时, a <= b有时不会评估为真。 If a and b are two finite float variables, a <= b evaluate to true exactly when the rational represented by a is less than or equal to the rational represented by b . 如果ab是两个有限的float变量,当a表示的有理数小于或等于b表示的有理数时, a <= b恰好评估为真。 The only little glitch one may perceive is actually not a glitch but a strict interpretation of the rule above: +0.0 <= -0.0 evaluates to true, because “the rational represented by +0.0 ” and “the rational represented by -0.0 ” are both 0. 人们可能感觉到的唯一小故障实际上不是故障,而是对上述规则的严格解释: +0.0 <= -0.0评估为真,因为“由+0.0表示的理性”和“由-0.0表示的理性”是都是0。

Similarly, there is nothing approximate about == between floats : two finite float variables a and b make a == b true if and only if the rational represented by a and the rational represented by b are the same. 类似地, 浮点数之间没有关于==近似值 :当且仅当由a表示的理性和由b表示的有理数相同时,两个有限的float变量ab使得a == b真。

Within a if (f != 0.0) condition, the value of f cannot be a representation of zero, and thus a division by f cannot be a division by zero. if (f != 0.0)条件内, f的值不能表示为零,因此除以f不能除以零。 The division can still overflow. 分裂仍然可能溢出。 In the particular case of value / maximum , there cannot be an overflow because your function requires 0 ≤ value ≤ maximum . value / maximum的特定情况下,不会出现溢出,因为您的函数需要0 ≤ value ≤ maximum And we don't need to wonder whether in the precondition means the relation between rationals or the relation between floats, since the two are essentially the same. 我们不需要怀疑前提条件中的是否意味着有理数之间的关系或者浮点数之间的关系,因为两者基本上是相同的。

This said 这说

C99 allows extra precision for floating-point expressions, which has been in the past wrongly interpreted by compiler makers as a license to make floating-point behavior erratic (to the point that the program if (m != 0.) { if (m == 0.) printf("oh"); } could be expected to print “oh” in some circumstances). C99允许浮点表达式的额外精度,这在过去被编译器制造商错误地解释为许可使浮点行为不稳定 (程序if (m != 0.) { if (m == 0.) printf("oh"); }可能会在某些情况下打印“哦”)。

In reality, a C99 compiler that offers IEEE 754 floating-point and defines FLT_EVAL_METHOD to a nonnegative value cannot change the value of m after it has been tested. 实际上,提供IEEE 754浮点并将FLT_EVAL_METHOD定义为非负值的C99编译器在测试后不能更改m的值。 The variable m was set to a value representable as float when it was last assigned, and that value either is a representation of 0 or it isn't. 变量m设置为上次分配时可表示为float的值,该值表示为0或不是。 Only operations and constants can have excess precision (See the C99 standard, 5.2.4.2.2:8). 只有操作和常量才能具有过高的精度(参见C99标准,5.2.4.2.2:8)。

In the case of GCC, recent versions do what is proper with -fexcess-precision=standard , implied by -std=c99 . 对于GCC,最新版本使用-fexcess-precision=standard执行适当的-fexcess-precision=standard ,由-std=c99隐含。

Further reading 进一步阅读

  • David Monniaux's description of the sad state of floating-point in C a few years ago (first version published in 2007). David Monniaux几年前描述了C中浮点的悲伤状态(2007年发布的第一个版本)。 David's report does not try to interpret the C99 standard but describes the reality of floating-point computation in C as it was then, with real examples. David的报告并没有尝试解释C99标准,而是通过实例来描述C中浮点计算的实际情况。 The situation has much improved since, thanks to improved standard-compliance in compilers that care and thanks to the SSE2 instruction set that renders the entire issue moot. 由于编译器的标准兼容性得到了提高,并且由于SSE2指令集使得整个问题没有实际意义,因此情况有了很大改善。

  • The 2008 mailing list post by Joseph S. Myers describing the then current GCC situation with floats in GCC (bad), how he interpreted the standard (good) and how he was implementing his interpretation in GCC (GOOD). 约瑟夫·迈尔斯(Joseph S. Myers)在2008年的邮件列表中描述了目前GCC在GCC浮动的情况(糟糕),他如何解释标准(好)以及他如何在GCC(GOOD)中实施他的解释。

In this case with the limited range, it should be OK. 在这种情况下,范围有限,应该没问题。 In general a check for zero first will prevent division by zero, but there's still a chance of getting overflow if the divisor is close to zero and the dividend is a large number, but in this case the dividend will be small if the divisor is small (both could be close to zero without causing overflow). 一般来说,首先检查零会阻止除零,但如果除数接近零并且被除数是一个大数,则仍有可能出现溢出,但在这种情况下,如果除数很小,则被除数会很小(两者都可以接近零而不会导致溢出)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM