2016-12-04 45 views
3

我一直在試圖找到一種方法來確保雙「值」的長度不大於10.但是,由於我沒有將它舍入到一定數量的小數位,所以這變得難以編程。如何四捨五入到n長度(不是n個小數位)?

例如,1234567.8912和12.345678912都大於10位數,但它們必須舍入到不同的小數位數。我的邏輯是找到小數點出現的位置,並將double舍入爲「10位小數點前的位數」。

我創建了兩種不同的方法,兩種方法似乎都不能正常工作。

if ((Double.toString(value)).length()> 10){ 
     int counter = 0; 
     double no_of_dec = 1; 
     double no_of_int = 1; 
     double new_value = 0; 
     for (int i = 0; i< (Double.toString(value)).length(); i++){ 
      if ((Character.toString((Double.toString(value)).charAt(i))).equals(".")){ 
       counter = 1; 
      } if (counter == 1){ 
       no_of_dec = no_of_dec * 10; 
      } else if (counter == 0){ 
       no_of_int = no_of_int * 10; 
      } 
     } 
     no_of_dec = no_of_dec/(no_of_int); 
     new_value = (double)Math.round(value * 100d/100d); 
     return Double.toString(new_value); 
    } else { 
     return Double.toString(value); 
    } 


    if ((Double.toString(value)).length()> 10){ 
     double no_of_dec = 0; 
     double no_of_int = 0; 
     double new_value = 0; 
     for (int i = 0; i< (Double.toString(value)).length(); i++){ 
      while (!(Character.toString((Double.toString(value)).charAt(i))).equals(".")){ 
       no_of_int = no_of_int + 1; 
      } 
     } 
     no_of_dec = (Double.toString(value)).length() - no_of_int; 
     no_of_dec = no_of_dec * 10; 
     new_value = (double)Math.round(value * no_of_dec/no_of_dec); 
     return Double.toString(new_value); 
    } else { 
     return Double.toString(value); 
    } 
} 
+0

如果號碼是'0.1234567891'沒有前導零得到算作是數字嗎? – 4castle

+0

什麼_「他們將被舍入到不同的小數位數」_是什麼意思?但是,您能舉一個例子作爲輸入和預期輸出。 – snr

+0

@ 4castle是的,它確實是 – assassinweed2

回答

3

我就是這麼做的:

private static BigDecimal getRounded(double n, int totalDigits) { 

    String nString = Double.toString(n); // transform to string to make the job easier 

    if(nString.contains(".")) { 
     int dotPos = nString.indexOf("."); // = number of digits before the decimal point 

     int remainingDigits = totalDigits - dotPos; // = remaining digits after the decimal point 

     return new BigDecimal(nString).setScale(remainingDigits, BigDecimal.ROUND_HALF_UP); // round 
    } 

    return new BigDecimal(n); 
} 

這是我的測試:

double n = 1234567.8912; 
System.out.println(getRounded(n, 10)); 

n = 12.345678915; 
System.out.println(getRounded(n, 10)); 

而這個結果:

1234567.891 
12.34567892 

演示:http://ideone.com/my7eB2

0

BigDecimal有這樣的操作:

double truncate(double value) { 
    BigDecimal b = new BigDecimal(String.valueOf(value)); 
    b = b.round(new MathContext(10)); 
    return b.doubleValue(); 
} 

沒有爲使用BigDecimal(String)構造,而不是通過BigDecimal(double)構造一個原因。雙打和浮動不是基數10的數字,所以它們並不完全代表我們在打印時看到的值; constructor documentation對此有很好的說明。這不是Java獨有的,在大多數語言中都是如此。

更新:

4castle指出,上述不會爲一個幅度小於1非零數字的工作,因爲BigDecimal的不考慮零整數部分顯著數字。您可以解決的是:

double truncate(double value) { 
    int precision = 10; 
    if (value != 0 && Math.abs(value) < 1) { 
     precision--; 
    } 

    BigDecimal b = new BigDecimal(String.valueOf(value)); 
    b = b.round(new MathContext(precision)); 
    return b.doubleValue(); 
} 

更新2:

反斜線指出,這是更復雜的比上面-1和1之間的數字非零我敢肯定,這可以計算確切的精度需要的,但我認爲這是簡單的通過增加1四捨五入的目的只是消除此問題:

double truncate(double value) { 
    BigDecimal b = new BigDecimal(String.valueOf(value)); 

    MathContext context = new MathContext(10); 
    if (value > 0 && value < 1) { 
     b = b.add(BigDecimal.ONE); 
     b = b.round(context); 
     b = b.subtract(BigDecimal.ONE); 
    } else if (value < 0 && value > -1) { 
     b = b.subtract(BigDecimal.ONE); 
     b = b.round(context); 
     b = b.add(BigDecimal.ONE); 
    } else { 
     b = b.round(context); 
    } 

    return b.doubleValue(); 
} 
+1

這絕對是最好的解決方案,但我發現前面的零(見上面的我的評論)不算作精度的一部分,所以在這種情況下它給出了太多的數字。 – 4castle

+2

將其重新轉換爲「double」將銷燬「BigDecimal」完成的所有操作。 'BigDecimal'確實有'double'的構造函數。 – EJP

+1

事實上,它不會只返回一個數字小於1的數字。它會返回一個數字**,每個前導零**。例如,我用'0.00034567089445515'試過這種方法:返回長度爲14位數的「0.0003456708945」:10 + 4前導零。如果我輸入'0.0000000034567089445515',則返回'0.000000003456708945',這是19位數字:10 +9前導零。 [演示這裏](http://ideone.com/BqJVZg) – BackSlash