- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们正在解决与数字精度相关的错误。我们的系统收集一些数字并给出它们的总和。问题是系统不保留数字精度,例如300.7 + 400.9 = 701.599...,而预期结果为 701.6。精度应该适应输入值,因此我们不能将结果舍入到固定精度。
问题很明显,我们使用 double 作为值,并且加法会累积十进制值的二进制表示形式的误差。
数据路径如下:
现在,我认为最佳解决方案是将所有内容转换为十进制格式。毫不奇怪,人们面临着采用最便宜的解决方案的压力。事实证明,将 double 转换为 BigDecimal在添加几个数字之前,对于以下示例中的情况 B 有效:
import java.math.BigDecimal;
public class Arithmetic {
public static void main(String[] args) {
double a = 0.3;
double b = -0.2;
// A
System.out.println(a + b);//0.09999999999999998
// B
System.out.println(BigDecimal.valueOf(a).add(BigDecimal.valueOf(b)));//0.1
// C
System.out.println(new BigDecimal(a).add(new BigDecimal(b)));//0.099999999999999977795539507496869191527366638183593750
}
}
更多相关信息: Why do we need to convert the double into a string, before we can convert it into a BigDecimal? Unpredictability of the BigDecimal(double) constructor
我担心这样的解决方法会是一颗定时炸弹。首先,我不太确定这个算法是否适用于所有情况。其次,仍然存在一些风险,即将来有人可能会实现一些更改并将 B 更改为 C,因为这个陷阱远不明显,甚至单元测试也可能无法揭示该错误。
我愿意接受第二点,但问题是:这个解决方法会提供正确的结果吗?是否存在某种情况
Double.valueOf("12345.12345").toString().equals("12345.12345")
是假的吗?根据 javadoc,鉴于 Double.toString 仅打印唯一表示基础 double 值所需的数字,因此当再次解析时,它会给出相同的 double 值吗?这对于我只需要添加数字并用这个神奇的 Double.toString(Double d) 打印总和的用例来说还不够吗?方法?需要明确的是,我确实更喜欢我所认为的干净的解决方案,在任何地方都使用 BigDecimal,但我缺乏说服力,我的意思是理想的例子,在加法之前转换为 BigDecimal无法完成上述工作。
最佳答案
如果无法避免解析为原始 double
或存储为 double,则应尽早转换为 BigDecimal
。
double
不能精确表示小数。 double x = 7.3;
中的值永远不会恰好是 7.3,而是非常接近它的值,从右侧第 16 位左右可见差异(给出 50 位小数左右) )。不要被打印可能精确地给出“7.3”这一事实所误导,因为打印已经进行了某种舍入,并且没有准确地显示数字。
如果您使用双
数字进行大量计算,微小的差异最终会累积起来,直到超出您的容忍度。因此,在需要小数的计算中使用 double 确实是一个定时炸弹。
[...] we expect values no longer than 10 digits total, 5 fraction digits.
我认为这个断言意味着您处理的所有数字都必须是 0.00001
的精确倍数,没有任何其他数字。您可以使用
new BigDecimal.valueOf(Math.round(doubleVal * 100000), 5)
这将为您提供具有 5 个小数位的数字的精确表示,即最接近输入 doubleVal
的 5 位小数位。这样您就可以纠正 doubleVal
和您最初想要的十进制数之间的微小差异。
如果您只是使用 BigDecimal.valueOf(double val)
,您将遍历您正在使用的 double 的字符串表示形式,这不能保证它是您想要的。它取决于 Double 类内部的舍入过程,该过程试图用最合理的十进制位数表示 7.3 的 double 近似值(可能是 7.30000000000000123456789123456789125)。它恰好导致“7.3”(并且,对开发人员来说,它经常匹配“预期”字符串),而不是“7.300000000000001”或“7.3000000000000012”,这对我来说似乎同样合理。
这就是为什么我建议不要依赖四舍五入,而是通过小数点移动 5 位自行进行舍入,然后四舍五入到最接近的 long,并构造一个缩小 5 位小数的 BigDecimal。这可以保证您获得(最多)5 位小数的精确值。
然后使用 BigDecimals 进行计算(如有必要,使用适当的 MathContext 进行舍入)。
当您最终必须将数字存储为 double 时,请使用BigDecimal.doubleValue()
。生成的 double 值将足够接近小数,上述转换肯定会给您提供与之前相同的 BigDecimal (除非您有非常大的数字,例如小数点前 10 位数字 - 您会迷失 无论如何,双
)。
附注仅当小数分数与您相关时,请务必使用BigDecimal
- 英国先令货币有时由 12 便士组成。将小数磅表示为 BigDecimal
会比使用 double 带来更严重的灾难。
关于java - 在加法之前将 double 转换为 BigDecimal 是否足以保留原始精度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54011168/
我正在尝试将一个字符串逐个字符地复制到另一个字符串中。目的不是复制整个字符串,而是复制其中的一部分(我稍后会为此做一些条件......) 但我不知道如何使用迭代器。 你能帮帮我吗? std::stri
我想将 void 指针转换为结构引用。 结构的最小示例: #include "Interface.h" class Foo { public: Foo() : mAddress((uint
这有点烦人:我有一个 div,它从窗口的左上角开始过渡,即使它位于文档的其他任何位置。我试过 usign -webkit-transform-origin 但没有成功,也许我用错了。有人可以帮助我吗?
假设,如果将 CSS3 转换/转换/动画分配给 DOM 元素,我是否可以检测到该过程的状态? 我想这样做的原因是因为我正在寻找类似过渡链的东西,例如,在前一个过渡之后运行一个过渡。 最佳答案 我在 h
最近我遇到了“不稳定”屏幕,这很可能是由 CSS 转换引起的。事实上,它只发生在 Chrome 浏览器 上(可能还有 Safari,因为一些人也报告了它)。知道如何让它看起来光滑吗?此外,您可能会注意
我正在开发一个简单的 slider ,它使用 CSS 过渡来为幻灯片设置动画。我用一些基本样式和一些 javascript 创建了一支笔 here .注意:由于 Codepen 使用 Prefixfr
我正在使用以下代码返回 IList: public IList FindCodesByCountry(string country) { var query =
如何设计像这样的操作: 计算 转化 翻译 例如:从“EUR”转换为“CNY”金额“100”。 这是 /convert?from=EUR&to=CNY&amount=100 RESTful 吗? 最佳答
我使用 jquery 组合了一个图像滚动器,如下所示 function rotateImages(whichHolder, start) { var images = $('#' +which
如何使用 CSS (-moz-transform) 更改一个如下所示的 div: 最佳答案 你可以看看Mozilla Developer Center .甚至还有例子。 但是,在我看来,您的具体示例不
我需要帮助我正在尝试在选中和未选中的汉堡菜单上实现动画。我能够为菜单设置动画,但我不知道如何在转换为 0 时为左菜单动画设置动画 &__menu { transform: translateX(
我正在为字典格式之间的转换而苦苦挣扎:我正在尝试将下面的项目数组转换为下面的结果数组。本质上是通过在项目第一个元素中查找重复项,然后仅在第一个参数不同时才将文件添加到结果集中。 var items:[
如果我有两个定义相同的结构,那么在它们之间进行转换的最佳方式是什么? struct A { int i; float f; }; struct B { int i; float f; }; void
我编写了一个 javascript 代码,可以将视口(viewport)从一个链接滑动到另一个链接。基本上一切正常,你怎么能在那里看到http://jsfiddle.net/DruwJ/8/ 我现在的
我需要将文件上传到 meteor ,对其进行一些图像处理(必要时进行图像转换,从图像生成缩略图),然后将其存储在外部图像存储服务器(s3)中。这应该尽可能快。 您对 nodejs 图像处理库有什么建议
刚开始接触KDB+,有一些问题很难从Q for Mortals中得到。 说,这里 http://code.kx.com/wiki/JB:QforMortals2/casting_and_enumera
我在这里的一个项目中使用 JSF 1.2 和 IceFaces 1.8。 我有一个页面,它基本上是一大堆浮点数字段的大编辑网格。这是通过 inputText 实现的页面上的字段指向具有原始值的值对象
ScnMatrix4 是一个 4x4 矩阵。我的问题是什么矩阵行对应于位置(ScnVector3),旋转(ScnVector4),比例(ScnVector3)。第 4 行是空的吗? 编辑: 我玩弄了
恐怕我是 Scala 新手: 我正在尝试根据一些简单的逻辑将 Map 转换为新 Map: val postVals = Map("test" -> "testing1", "test2" -> "te
输入: This is sample 1 This is sample 2 输出: ~COLOR~[Green]This is sample 1~COLOR~[Red]This is sam
我是一名优秀的程序员,十分优秀!