我正在尝试将float转换为BigDecimal然后做一些数学运算。之后我会要求Float的最终结果。
据我所知,使float成为BigDecimal数的唯一安全方法是使用字符串构造函数。
我有两种方法,但都没有用。两者都给了我额外的0.000001值
方法#1:
Float num1 = 13.846154f;
BigDecimal calculation = new BigDecimal(Float.toString(num1));
BigDecimal num2 = new BigDecimal("2.0").add(calculation);
Float finalResults = num2.floatValue();
方法#2:
Float num1 = 13.846154f;
BigDecimal calculation = new BigDecimal(Float.toString(num1));
BigDecimal num2 = new BigDecimal("2.0").add(calculation);
Float finalResults = Float.parseFloat(num2.toString());
当我将数字转换回浮动时,有没有办法安全地进行数学运算而不会失去精度?
编辑#1 我做了一些测试,发现了一些奇怪的东西。
Float original = 13.846154f;
BigDecimal originalNum = new BigDecimal(Float.valueOf(original));
BigDecimal numTwo = new BigDecimal("14.0");
BigDecimal numThree = new BigDecimal("20.0");
BigDecimal numFour = new BigDecimal("30.0");
numTwo = numTwo.add(originalNum);
numThree = numThree.add(originalNum);
numFour = numFour.add(originalNum);
它还在增加额外的0.000001 ..
答案 0 :(得分:2)
如果你想避免失去任何精度,你必须一直使用BigDeciml,使用一点BigDecimal可能毫无意义。
我建议使用double
,它的准确度是10亿倍(真的是~10 ^ 9 *)
如果您要使用float
,请不要使用Float
,因为这只会增加开销,无益。
如果您执行13.846154
,则这比float
支持的更精确。
System.out.println(13.846155f);
System.out.println(23.846155f);
System.out.println(33.846155f);
打印
13.846155
23.846155
33.846153 <- a representation error with this many digits.
相反,我建议你尝试
double finalResult = 13.846154 + 2.0;
顺便说一句
System.out.println(13.846154+ 2.0);
打印
15.846154
答案 1 :(得分:2)
new BigDecimal(double)
构造函数与从float
到double
的转换完全相同,因此如果您从float
值num1
开始,{{ 1}}将提供准确的new BigDecimal(num1)
等价物。
这可能不是您所期望的。例如,最接近的BigDecimal
到13.846154是13.84615421295166015625,因此这是float
和num1
的初始值。
calculation
加2是准确的,给出15.84615421295166015625。
下一个问题是将其转换为BigDecimal
以进行进一步计算。碰巧的是,它完全可以表示为float
,因此不会进一步降低精度。一般情况下,将float
转换为BigDecimal
将涉及四舍五入到最近的float
。
事实证明,此计算中的所有精度损失都发生在float
的初始化上。如果你这样做,没有与String之间的所有转换,只要初始使用num1
,你就会尽可能接近。
如果float
对于您的计算不够精确,但您需要float
传递给其他方法,请考虑使用float
或BigDecimal
进行整个计算除了最后一步。 double
BigDecimal
确实会将最接近的floatValue()
返回到float
的确切值。
有一种情况,使用BigDecimal
是有利的。如果您知道您希望BigDecimal是一个精确的小数部分,那么从该分数的String表示构造String
就可以得到它。写BigDecimal
之类的内容会得到new BigDecimal(1.0)
,其值为0.1000000000000000055511151231257827021181583404541015625,最接近的值的值为0.1。如果您已转换为BigDecimal
或float
,则通过double
转换将无效或导致精度损失。它无济于事。