浮点,是一个足以防止被零除的相等比较
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;
}
}
maximum
的取值范围可以是任何数,也可以是负数。value
的范围也可以是任何东西,尽管只有当输入在[0.0 - maximum]
范围内时,该函数才需要"有意义"。输出应始终在[0.0 - 1.0]
我想知道两个问题,关于这个:
- 这个相等比较是否足以确保函数永远不会被零除?
- 如果最大值是一个退化值(非常小或非常大),是否有机会函数将返回[0.0 - 1.0]之外的结果(假设值在正确的范围内)?
这是一个迟来的回答,澄清了与这个问题有关的一些概念:
返回value/maximum
在浮点数中,除零不是像整数除零那样的致命错误。由于您知道value
位于0.0
和maximum
之间,因此唯一可能发生的除零是0.0 / 0.0
,它被定义为生成NaN
。对于函数obtainRatio
来说,浮点值NaN
是一个完全可以接受的值,并且实际上是一个比0.0
更好的异常值,因为您建议的版本正在返回。
对浮点数的迷信只是迷信
在浮点数之间没有关于<=
的近似定义。a
略高于b
时,a <= b
的not有时求值为真。如果a
和b
是两个有限的float
变量,则a
表示的有理数小于或等于b
表示的有理数时,a <= b
的值为true。唯一的小故障实际上不是故障,而是对上述规则的严格解释:+0.0 <= -0.0
求值为真,因为"+0.0
表示的理性"answers"-0.0
表示的理性"都是0。
同样地,在浮点数之间没有关于==
的近似:float
的两个有限变量a
和b
使a == b
为真,当且仅当a
表示的有理数与b
表示的有理数相同。
在if (f != 0.0)
条件中,f
的值不能是0的表示,因此被f
除法不能是被0除法。该部门仍有可能人满为患。在value / maximum
的特殊情况下,不可能发生溢出,因为您的函数需要0 ≤ value ≤ maximum
。并且我们也不需要去怀疑前提条件中的≤
是指有理数之间的关系还是指浮点数之间的关系,因为两者本质上是相同的。
这说
C99允许浮点表达式的额外精度,这在过去被编译器制造商错误地解释为使浮点行为不稳定的许可证(以至于程序if (m != 0.) { if (m == 0.) printf("oh"); }
在某些情况下可能会打印"oh")。
实际上,提供IEEE 754浮点数并将FLT_EVAL_METHOD
定义为非负值的C99编译器在测试后不能改变m
的值。变量m
在最后一次赋值时被设置为可表示为float的值,该值要么表示0,要么不表示0。只有操作和常量可以具有超精度(参见C99标准,5.2.4.2.2:8)。
在GCC的情况下,最近的版本对-fexcess-precision=standard
做了正确的处理,由-std=c99
暗示。
进一步阅读
-
David Monniaux几年前对C语言中浮点的悲惨状态的描述(第一版于2007年发布)。David的报告并没有试图解释C99标准,而是用真实的例子描述了C语言中浮点计算的现实情况。由于编译器的标准遵从性得到了改进,并且由于SSE2指令集使整个问题变得没有意义,情况已经得到了很大的改善。
-
Joseph S. Myers在2008年邮件列表中的帖子,描述了当时GCC中浮动的情况(坏),他如何解释标准(好)以及他如何在GCC中实现他的解释(好)。
在有限范围的情况下,应该可以。一般来说,先检查零可以防止除零,但如果除数接近零并且被除数很大,仍然有可能发生溢出,但在这种情况下,如果除数很小,被除数就会很小(两者都可以接近零而不会导致溢出)。
- 如何在 c++ 中比较 2 个链表并将匹配的数据放入另一个链表中
- C++设置了一个用于排序的比较器和另一个用于唯一性的比较器
- 绘制一个对象,比较模具缓冲区的两个不同值
- 我如何将一个变量与另一个变量进行比较,例如我想如果(var1 > var2 x 1),然后执行此 c++
- 如何比较文件中包含的下一个字符
- 为 RocksDB 实现一个比较器
- 将当前多边形数据单元与下一个多边形单元格 - VTK 进行比较
- 比较最后一个字符,不区分大小写(带谓词?
- 如何键入定义一个专门的 std::set 模板,使用特定的比较函数实例化
- 与C++中不止一个字符进行比较
- 将 32 位浮点数和不强制转换的 32 位整数与双精度进行比较,当其中一个值可能太大而无法完全适合另一种类型时
- 在数组中仅比较一个字符
- 如何将一个值与整个数组进行比较
- 如何制作一个从文件中读取密码并与用户编写的密码进行比较的 c++ 程序
- C++:将当前时间与下一个工作时间进行比较
- 我怎样才能洗牌给定大小的数组并将其与C++中另一个相同大小的数组进行比较
- 比较一个链接列表与另一个黑名单与词频列表C++
- 为什么在汇编代码中比较一个在范围内的数字时会发生分支
- 是否有一种方法可以正确地比较一个float值是否大于/小于另一个
- 比较一个向量中向量的大小,得到最大的