2013-04-04 95 views
4

我知道这个问题是很多反复,但请看看语句第一比马克它已经回答了:)截断双精度到2位小数?

用于截断双重价值2位小数我使用的大多是随处提到的两个方面。下面

//this one 
    DecimalFormat dtime = new DecimalFormat("#.##"); 
    return Double.valueOf(dtime.format(val)); 
    //or the one below 
    BigDecimal bd = new BigDecimal(val); 
    BigDecimal rounded = bd.setScale(2, BigDecimal.ROUND_HALF_UP); 
    return rounded.doubleValue(); 

给他们的问题是,对于这两种方式我主要是在数据集中获得正确的四舍五入值。但奇怪的是,我同时获得了2.00000000000005或19.97999999999这样的值。

我没有得到的问题是,为什么只有几个值没有被舍入。什么可能是错的?

+1

[浮点可能重复不准确](http://stackoverflow.com/questions/4575643/floating-point-inaccuracies) – Ingo 2013-04-04 18:31:49

+1

投票结束:你不明白关于双精度/浮点精度的其他5786问题的答案。回去再读一遍。 – Ingo 2013-04-04 18:32:42

+0

你会得到“价值如”2.00000000000005,或者你得到2.00000000000005?如果你得到19。例如,9800000000000004,这可能是由于将四舍五入的值转换为二进制浮点引起的。正如其他答案中所解释的,这种转换会导致一些错误。如果得到2.00000000000005,那么还有一些其他问题,因为已经舍入为2.00的值在转换为浮点时将保持2。在后者情况下,Ingo以不正当的方式投票将其视为重复。 – 2013-04-04 18:39:12

回答

2

为了截断double值2个小数位,我使用了两种主要随处可见的方法。

他们都是错误的,因为他们正在尝试不可能的事情。有没有这样的东西截断双精度到小数点后2位,因为双打不要有小数位。他们有二进制的地方。见my answer here作证明。如果您想要小数位,则必须使用小数基数,即BigDecimalDecimalFormat

+0

@mKorbel只为你: - | – EJP 2013-04-05 00:05:09

0

问题是浮点数本质上是近似的,给定了基础表示。因此,您需要在近似值较好的地方使用它们,并在近似值不好的地方避免使用它们(例如财务)。

rounded.doubleValue()的调用仍会返回一个浮点数,所以它仍受到表示限制的影响。

有关更多信息,请参见

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

+0

喜欢这个值..我的意思是小数位数不被截断..抱歉的混淆 – Aneeque 2013-04-04 18:43:37

+0

了解。浮点表示没有内置精度。当你“截断”数字时,你只是将数字的某个部分清零,然后显示剩下的部分。如果原来的数字没有确切的浮点数表示,那么您会被表示可以提供的最好数字卡住,数字与您提供的数字相似。例如。如果没有19.98的精确浮点表示(使用你的例子),那么你将不得不处理任何表示“足够接近”。 – 2013-04-04 19:45:49

+0

thnx为明确答案:)。任何方式来解决这个问题除了截断为一个字符串? – Aneeque 2013-04-04 20:28:27

-1

我是新来的,但保持在我面前的一切我是这样做的。现在请注意,这是一个数学截断,除了在每行之后的调试中,我不会将其转换为字符串。

这不是优雅,但似乎工作。这纯粹是一个解决问题的框架。

无论如何;

import java.util.Scanner; 
public class TestConstructs 
{ 
private static double w; 
private static int w1; 
private static double w2; 
private static double w3; 
private static int w4; 
private static double w5; 
private static double w6; 

public static void main(String[] args) 
{ 
    // TODO Auto-generated method stub 
    TestConstructs foo = new TestConstructs(); 
    foo.setWage(w); 

} 

public void setWage(double w) 
{ 

    Scanner input = new Scanner(System.in); 
    System.out.println("Enter Wage: "); //enter something longish like 30987.978654 or w/e 
    w = input.nextDouble(); 
    w1 = (int)w; 
    System.out.printf("%d w1\n",w1); 
    w2 = w - w1; 
    System.out.printf("%.3f w2\n",w2); 
    w3 = w2*100; 
    System.out.printf("%.3f w3\n",w3); 
    w4 = (int)w3; 
    System.out.printf("%d w4\n",w4); 
    w5 = (double)w4; 
    System.out.printf("%.3f w5\n",w5); 
    w6 = 0 + w5/100; 
    System.out.printf("%.3f w6\n",w6); 
    w = w1 + w6; 

    System.out.printf("%.3f final value\n",w); //.3 to show zero 
    input.close(); 
} 

} 

我在最后 有什么输入工资: 30987.978654 30987 W1 0.979 W2 97.865 W3 97 W4 97.000 W5 0.970 W6 30987.970终值

+0

它不起作用。看到我的答案在http://stackoverflow.com/questions/153724/how-to-round-a-number-to-n-decimal-places-in-java作证明。 – EJP 2013-09-29 20:29:04

+0

虽然这样做你的方式做了这个项目圆了,我不得不将TRUNCATE两位小数,而不是圆。另外,在我参加的课程中,我无法使用超出课程范围的方法。 – user2829229 2013-09-29 22:02:29

+0

在另一个笔记我知道双打不绑定的地方,所以没有绝对截断没有字符串转换。这样做的目的是尽可能多地丢弃数字垃圾到第二个小数点以外,double中的任何内容都不是精确的,但是使用我写的有效地破坏了位置.00(x)处整数的考虑,这正是我所需要的。 – user2829229 2013-09-29 22:07:15