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

时间:2014-05-06 21:55:31

标签: c++ c floating-point

// 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;
    }
}

maximum的范围可以是任何内容,包括负数。 value的范围也可以是任何东西,但该功能仅需要使" sense"当输入在[0.0 - maximum]范围内时。输出应始终在[0.0 - 1.0]

的范围内

我有两个问题,我想知道这个问题:

  • 这种相等比较是否足以确保函数永远不会除以零?
  • 如果最大值是退化值(非常小或非常大),函数是否有可能返回[0.0 - 1.0]之外的结果(假设值在正确的范围内)?

2 个答案:

答案 0 :(得分:14)

这是一个迟到的答案,澄清了与问题相关的一些概念:

只返回值/最大值

在浮点数中,除零不是整数除零的致命错误。 由于您知道value介于0.0maximum之间,因此可以发生的唯一除零是0.0 / 0.0,定义为生成NaN。浮点值NaN是函数obtainRatio返回的完全可接受的值,实际上是一个比0.0更好的异常值,因为您提出的版本正在返回。

关于浮点的迷信只是迷信

浮动之间<=的定义没有任何近似值。当a <= b略高于a时,b 有时评估为true。如果ab是两个有限float个变量,那么当a <= b所代表的理性小于或等于理性代表时,a会完全评估为真按b。人们可能感觉到的唯一一点小故障实际上并不是一个小故障,而是对上述规则的严格解释:+0.0 <= -0.0评估为真,因为“+0.0代表的理性”和{-0.0代表的理性1}}“都是0。

同样,浮动之间没有==近似值:两个有限float个变量ab生成a == b当且仅当a表示的理性和b表示的理性相同时才为真。

if (f != 0.0)条件下,f的值不能表示为零,因此f的除法不能除以零。分裂仍然可能溢出。在value / maximum的特定情况下,由于您的函数需要0 ≤ value ≤ maximum,因此不会出现溢出。而且我们不需要怀疑前提条件中的是否意味着理性之间的关系或者浮点数之间的关系,因为这两者基本上是相同的。

这说

C99允许浮点表达式具有额外的精度,这已经被编译器制造商错误地解释为使得浮点行为不稳定的许可(到程序{{ 1}}可能会在某些情况下打印“哦”。

实际上,提供IEEE 754浮点并将if (m != 0.) { if (m == 0.) printf("oh"); }定义为非负值的C99编译器在测试后不能更改FLT_EVAL_METHOD的值。变量m设置为上次分配时表示为float的值,该值表示为0或者不是。只有操作和常量才能具有过高的精度(参见C99标准,5.2.4.2.2:8)。

对于GCC,最新版本使用m执行适当的操作,-fexcess-precision=standard暗示。

进一步阅读

  • David Monniaux description几年前C中浮点状态的悲惨状态(2007年发布的第一版)。 David的报告并没有尝试解释C99标准,而是通过实例来描述C中浮点计算的实际情况。这种情况得到了很大的改善,这要归功于编译器的标准兼容性得到了改善,因为SSE2指令集使整个问题变得没有实际意义。

  • 约瑟夫·迈尔斯的2008 mailing list post描述当时海湾合作委员会当前GCC的情况(不好),他如何解释标准(好)以及他如何在GCC中实施他的解释(好) )。

答案 1 :(得分:4)

在这种情况下,范围有限,应该没问题。一般来说,首先检查零会阻止除零,但如果除数接近于零并且被除数是一个大数,那么仍然有可能出现溢出,但在这种情况下,如果除数是一个很大的数,则分红将很小。除数很小(两者都可以接近零而不会导致溢出)。