Тип данных double или float не корректно вводится в цикле?

В цикле я добавляю 0,10, пока не достигну желаемого #, и получаю индекс. Это мой код:

<code>    private static int getIndexOfUnits(float units) {
    int index = -1;
    float addup = 0.10f;
    for(float i = 1.00f; i < units; i=(float)i+addup) {
        index++;
        System.out.println("I = " + i + " Index = " + index);
    }

    return index;
}
</code>

Если количество пройденных единиц составляет 5,7, я вижу:

<code>I = 1.0 Index = 0
I = 1.1 Index = 1
I = 1.2 Index = 2
I = 1.3000001 Index = 3
I = 1.4000001 Index = 4
I = 1.5000001 Index = 5
I = 1.6000001 Index = 6
I = 1.7000002 Index = 7
I = 1.8000002 Index = 8
I = 1.9000002 Index = 9
I = 2.0000002 Index = 10
I = 2.1000001 Index = 11
I = 2.2 Index = 12
I = 2.3 Index = 13
I = 2.3999999 Index = 14
I = 2.4999998 Index = 15
I = 2.5999997 Index = 16
I = 2.6999996 Index = 17
I = 2.7999995 Index = 18
I = 2.8999994 Index = 19
I = 2.9999993 Index = 20
I = 3.0999992 Index = 21
I = 3.199999 Index = 22
I = 3.299999 Index = 23
I = 3.399999 Index = 24
I = 3.4999988 Index = 25
I = 3.5999987 Index = 26
I = 3.6999986 Index = 27
I = 3.7999985 Index = 28
I = 3.8999984 Index = 29
I = 3.9999983 Index = 30
I = 4.0999985 Index = 31
I = 4.1999984 Index = 32
I = 4.2999983 Index = 33
I = 4.399998 Index = 34
I = 4.499998 Index = 35
I = 4.599998 Index = 36
I = 4.699998 Index = 37
I = 4.799998 Index = 38
I = 4.8999977 Index = 39
I = 4.9999976 Index = 40
I = 5.0999975 Index = 41
I = 5.1999974 Index = 42
I = 5.2999973 Index = 43
I = 5.399997 Index = 44
I = 5.499997 Index = 45
I = 5.599997 Index = 46
I = 5.699997 Index = 47
</code>

Если единицы - это большое число, например 18,90 или 29,90, это дает неверный индекс. Индекс обычно на 1 меньше, чем должен быть. Было добавлено только 0.10, но после 2.3 он получает 2.39999 .... при добавлении 0.10 к нему. Я считаю, что это вопрос точности. Как справиться с этим и убедиться, что я получаю правильный индекс на больших # также независимо от использования float или double.

Есть идеи !!!!

 James K Polk07 мая 2012 г., 13:21
Вы понимаете, что 0.10 не имеет точного представления в java (и на любом другом языке) системе с плавающей запятой? Неважно, какую точность вы предоставляете, даже если у java был тип с плавающей запятой с точностью до миллиона битов. Вам нужно использовать специализированный десятичный класс или класс дробей.

Ответы на вопрос(5)

ерация).

Попробуйте вычислить I каждый раз:

I = 1.0f + (i*addup);

И вы не будете накапливать ошибки с плавающей запятой.

Java предоставляет класс из пакета импорта:import java.text.DecimalFormat называетсяDecimalFormat, Его подпись:

DecimalFormat myFormat = new DecimalFormat("0.0");

Он принимает аргумент String, где вы указываете, как вы хотите, чтобы форматирование отображалось.

Вот как вы можете применить его к своему коду:

DecimalFormat myFormat;
private static int getIndexOfUnits(float units) {
myFormat = new DecimalFormat("0.0");
int index = -1;
float addup = 0.10f;
for(float i = 1.00f; i < units; i=(float)i+addup) {
    index++;
    System.out.println("I = " + myFormat.format(i) + " Index = " + index);
}

return index;

}

В вашем println вы можете видеть, что класс DecimalFormat 'sformat() метод вызываетсяfloat i используя ссылку на объект myFormat на DecimalFormat - здесь происходит форматирование.

Решение Вопроса

Гид с плавающей точкой:

Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and instead I get a weird result like 0.30000000000000004?

Because internally, computers use a format (binary floating-point) that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.

When the code is compiled or interpreted, your “0.1” is already rounded to the nearest number in that format, which results in a small rounding error even before the calculation happens.

Вы не можете использоватьfloat или жеdouble если вам нужны цифры, чтобы сложить точно. использованиеBigDecimal вместо.

BigDecimal поможет вам. Следующий пример может быть полезным для вас

BigDecimal decimal=new BigDecimal(10.0);
    for (int i = 0; i < 10; i++) {
        decimal=decimal.add(new BigDecimal(.1));
        System.out.println(decimal.floatValue());

    }

что формат, который использует float, не может представлять все десятичные числа, поэтому точность иногда теряется.

использованиеBigDecimal вместо.

Ваш ответ на вопрос