两个浮点数的安全除法
A safe way to divide two floating point numbers?
什么是除两个IEEE 754浮点数最安全的方法?
在我的情况下,语言是JavaScript,但我想这并不重要。目标是避免常见的浮点错误。
我读到有人可以使用"修正因子"(cf)(例如10提升到某个数字,例如10^10),如下所示:
(a * cf) / (b * cf)
但我不确定这对除法有什么影响?
顺便说一句,我已经看了其他关于Stack Overflow的浮点文章,我仍然没有找到一个关于如何除两个浮点数的文章。如果答案是在加法和除法时处理浮点问题的解决方案之间没有区别,那么请回答这个问题。 编辑:有人在评论中问我,我指的是哪些陷阱,所以我想我应该在这里为那些没有阅读评论的人补充一点:
当将0.1和0.2相加时,您期望得到0.3,但使用浮点运算您会得到0.30000000000000004(至少在JavaScript中)。这只是一个常见陷阱的例子。
上面的问题在Stack Overflow上讨论了很多次,但是我不知道除法时会发生什么,也不知道它是否与加法或乘法时发现的陷阱不同。可能没有风险,在这种情况下,这将是一个完美的答案。
最安全的方法是简单地将它们分开。任何预缩放要么什么都不做,要么增加舍入误差,要么导致溢出或下溢。
如果按2的幂进行预调,可能会导致溢出或下溢,但不会对结果产生影响。
如果您按任何其他数字进行预进,您将在乘法中引入额外的舍入步骤,这可能导致除法结果的舍入误差增加。
如果你简单地除以,结果将是最接近两个输入之比的可表示数字。
IEEE 754 64位浮点数非常精确。几乎10^16分之一的差别都可以表示出来。
有一些操作,比如取底运算和精确比较,即使是极低的意义位也很重要。如果您一直在阅读有关浮点陷阱的文章,那么您应该已经看到了一些例子。避免这些。将输出四舍五入到适当的小数位数。
下面的程序演示了使用从10到1e20的每个10的幂作为比例因子的效果。大多数得到的结果与不相乘相同,6.0,这也是有理数算术结果。
您可以通过更改a
和b
的初始化式来尝试不同的除法问题。程序在四舍五入为双精度后打印出它们的精确值。
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
double mult = 10;
double a = 2;
double b = 1.0 / 3.0;
System.out.println("a=" + new BigDecimal(a));
System.out.println("b=" + new BigDecimal(b));
System.out.println("No multiplier result="+(a/b));
for (int i = 0; i < 20; i++) {
System.out.println("mult="+mult + " result="+((a * mult) / (b * mult)));
mult *= 10;
}
}
}
输出:a=2
b=0.333333333333333314829616256247390992939472198486328125
No multiplier result=6.0
mult=10.0 result=6.000000000000001
mult=100.0 result=6.000000000000001
mult=1000.0 result=6.0
mult=10000.0 result=6.000000000000001
mult=100000.0 result=6.000000000000001
mult=1000000.0 result=6.0
mult=1.0E7 result=6.000000000000001
mult=1.0E8 result=6.0
浮点除法将产生与加法或乘法运算完全相同的"陷阱",并且没有任何预缩放将修复它-最终结果就是最终结果,它是IEEE-754中导致"问题"的内部表示。
解决方案是在计算过程中完全忘记这些精度问题,并尽可能晚地执行舍入,即只有在显示计算结果时才执行舍入,在使用.toFixed()
函数将数字转换为字符串的时候,正是为此目的提供的。
.tofixed()不是浮点数除法的好方法。使用javascript试试:4.11/100,你会惊讶的。
4.11 / 100 = 0.041100000000000005
不是所有的浏览器都得到相同的结果。正确的解决方案是将浮点数转换为整数:
parseInt(4.11 * Math.pow(10, 10)) / (100 * Math.pow(10, 10)) = 0.0411
- 如何在读取XLS/XLSX本地文件时,使用IE的javascript代码启用未标记为安全的ActiveX控件
- 使用javascript存储变量的最安全方式
- 是否存在React Native“;WEB代码安全防护”;
- 内容安全策略:页面's设置阻止加载资源
- 如何通过安全的https连接在javascript中使用基于soap xml的Web服务
- 导致内容安全策略(CSP)冲突错误的本地jquery.js文件
- 如何在Google chrome安全首选项文件中创建扩展安全哈希代码
- ES6 模板文字是否比 eval 更安全
- CORS保持在SecurityError上:操作不安全
- 旋转木马;启用内容安全策略时无法工作
- 从自己的安全系统中重新找回自己
- 关于ajax的安全问题
- 如何使用app和secret进行安全的解析初始化
- 是一个javascript bookmarklet,可以设置破坏跨域安全的域cookie
- Extjs、Chrome扩展和内容安全策略
- createObjectURL blob url在Firefox中不安全
- java安全doPrivileged方法如何阻止任意脚本
- addthis:addthis实用程序框架的JS安全错误
- 当eval只执行服务器端数据时,在javascript中使用eval是否安全
- 两个浮点数的安全除法