是否存在舍入算法来撤消基数2转换并推断精度? *希望在java *

时间:2012-01-19 08:16:23

标签: java rounding

如果我有一个像3.01的数字,计算机似乎认为最好的双倍是64位数字:

3.0099999999999997868371792719699442386627197265625

是否有一些方法比寻找超过四个9或0更好,我可以一般“圆”到精确的基数10表示?

是否有一个算法需要3.00999999 ...混乱并返回3.01而不指定我想要那么精确。

我认为我正在处理的大多数数字都应该足够小,以至于64位不会有歧义。

3 个答案:

答案 0 :(得分:2)

否 - 因为大概是可能实际指定了3.0099999999999997868作为输入数字,并且不希望将相同的值四舍五入为3.01。基本上,当您从十进制值转换为二进制浮点时,您丢失了信息 - 您无法获得该信息。

如果您对小数值感兴趣而不仅仅是幅度,则应考虑使用BigDecimal代替double。 (这些值代表什么?)

编辑:正如其他答案所指出的那样,当你只使用toString时,Java会给你3.01,但是你得到了原始值。这在Double.toString

中指定
  

m或a的小数部分必须打印多少位数?必须至少有一个数字来表示小数部分,并且除此之外必须有多个,但只有多少,更多的数字才能唯一地将参数值与double类型的相邻值区分开来。也就是说,假设x是由该方法为有限非零参数d生成的十进制表示所表示的精确数学值。那么d必须是最接近x的double值;或者如果两个double值同样接近x,那么d必须是其中之一,d的有效位的最低有效位必须为0.

如果这对你来说足够好,它会让生活更轻松......但听起来你应该从根本上考虑它。

答案 1 :(得分:1)

如果您想要10位精度,则需要舍入到该精度。即使您使用BigDecimal,也可以避免表示错误,但迟早您将不得不知道如何处理精度。

double d = 3.01;
System.out.println(d); // rounds the answer slightly

打印

3.01

表示和舍入错误有很多变通方法,但是内置工具通常会为您处理它。

答案 2 :(得分:1)

很明显,你不能指望总是得到原始数字,因为有很多数字映射到同一个浮点数。例如,您无法区分这些数字:

3.0099999999999997868371792719699442386627197265625
3.009999999999999786837179271969944238662
3.009999999999999786837179271
3.0099999999999997
3.01

然而,Python对此有一个有趣的看法:如果你给它号码3.0099999999999997868371792719699442386627197265625,它将回复3.01:

Python 2.7.2+ (default, Nov 30 2011, 19:22:03) 
[GCC 4.6.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3.0099999999999997868371792719699442386627197265625
3.01

这是因为3.01是提供相同浮点数的最短字符串。换句话说,它是最短的x,所以

float(repr(x)) == x

其中repr是将对象转换为字符串的Python函数(此处将3.0099...转换为3.01),float将字符串转换为浮点数。 / p>

显然有许多字符串会产生相同的内部浮动,但这是最短的,因此“可能”就是你的意思。

此功能为added in Python 2.7,作为Python 3.1功能的后端。它是discussed in Issue1580,您应该能够在那里找到代码,并在需要时将其转换为Java。