2016-12-04 3 views
3

Я пытался найти способ убедиться, что длина двойного значения не больше 10. Однако это становится трудно программировать, так как я не округлю его до определенного количества десятичных знаков.Как объединить удвоенную и n длину (не n десятичных знаков)?

Например, 1234567.8912 и 12.345678912 оба больше, чем 10 цифр, однако они должны быть округлены до разного количества знаков после запятой. Моя логика заключалась в том, чтобы найти место десятичной точки и округлить двойное значение до «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(); 
} 

Существует причина для использования (String) конструктора BigDecimal а не (двойной) конструктора BigDecimal. double и floats не являются базовыми 10 числами, поэтому они не точно представляют значения, которые мы видим при их печати; constructor documentation имеет хорошую иллюстрацию этого. Это не уникально для Java и истинно на большинстве языков.

Update:

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(); 
} 

Update 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

Это, безусловно, лучшее решение, но я обнаружил, что начальный ноль (см. мой комментарий выше) не считается частью точности, поэтому в этом случае он дает 1 слишком много цифр. – 4castle

+2

Возвращая его в «double», уничтожает все, что было сделано «BigDecimal». И 'BigDecimal' имеет конструктор из' double'. – EJP

+1

На самом деле это не просто возвращает еще одну цифру с номерами меньше 1. Она возвращает еще одну цифру ** за первый ноль **. Например, я пробовал этот метод с '0.00034567089445515': он возвращает' 0.0003456708945', который составляет 14 цифр: 10 + 4 ведущих нуля. Если я вхожу в try с '0.0000000034567089445515', он возвращает' 0,000000003456708945', что составляет 19 цифр: 10 + 9 наивысших нулей. [Демо здесь] (http://ideone.com/BqJVZg) – BackSlash