Погрешности округления?

     defaultConfig {

    minSdkVersion 16
    targetSdkVersion 25  

    multiDexEnabled true
}

Просто установите это в файле build.gradle вашего приложения

22
задан Sildoreth 7 April 2015 в 18:57
поделиться

9 ответов

It is true.

It is an inherent limitation of how floating point values are represented in memory in a finite number of bits.

This program, for instance, prints "false":

public class Main {
  public static void main(String[] args) {
    double a = 0.7;
    double b = 0.9;
    double x = a + 0.1;
    double y = b - 0.1;
    System.out.println(x == y);
  }
}

Instead of exact comparison with '==' you usually decide on some level of precision and ask if the numbers are "close enough":

System.out.println(Math.abs(x - y) < 0.0001);
51
ответ дан 29 November 2019 в 03:20
поделиться

This applies to Java just as much as to any other language using floating point. It's inherent in the design of the representation of floating point values in hardware.

More info on floating point values:

What Every Computer Scientist Should Know About Floating-Point Arithmetic

26
ответ дан 29 November 2019 в 03:20
поделиться

Yes, representing 0.1 exactly in base-2 is the same as trying to represent 1/3 exactly in base 10.

8
ответ дан 29 November 2019 в 03:20
поделиться

Это всегда верно. Есть некоторые числа, которые нельзя точно представить с помощью представления с плавающей запятой. Рассмотрим, например, пи. Как бы вы представили число, состоящее из бесконечных цифр, в ограниченном хранилище? Поэтому при сравнении чисел вы должны проверить, не меньше ли разница между ними, чем какой-то эпсилон. Кроме того, существует несколько классов, которые могут помочь вам добиться большей точности, например BigDecimal и BigInteger.

4
ответ дан 29 November 2019 в 03:20
поделиться

Yes, as other answers have said. I want to add that I recommend you this article about floating point accuracy: Visualizing floats

2
ответ дан 29 November 2019 в 03:20
поделиться

Большинство процессоров (и компьютерных языков) используют арифметику с плавающей запятой IEEE 754. Используя эту нотацию, есть десятичные числа, которые не имеют точного представления в этой нотации, например 0,1. Таким образом, если вы разделите 1 на 10, вы не получите точного результата. При выполнении нескольких расчетов подряд ошибки суммируются. Попробуйте следующий пример на python:

>>> 0.1
0.10000000000000001
>>> 0.1 / 7 * 10 * 7 == 1
False

Это не совсем то, что вы ожидаете математически.

Кстати: Распространенное заблуждение относительно чисел с плавающей запятой заключается в том, что результаты неточны и их нельзя безопасно сравнивать. Это верно только в том случае, если вы действительно используете дроби чисел. Если вся ваша математика находится в целочисленной области, double и float работают точно так же, как ints, и их также можно безопасно сравнивать. Их можно безопасно использовать, например, в качестве счетчиков петель.

2
ответ дан 29 November 2019 в 03:20
поделиться

Верно. Обратите внимание, что Java не имеет к этому никакого отношения, проблема заключается в математике с плавающей запятой на ЛЮБОМ языке.

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

Случай, произошедший давным-давно в школе. Учитель вводного класса поставил задачу на выпускном экзамене, которая оказалась настоящей дурацкой для многих лучших учеников - она ​​не работала, и они не знали, почему. (Я видел это как лаборант, меня не было в классе.) В конце концов некоторые начали просить меня о помощи, и некоторые исследования выявили проблему: их никогда не учили о внутренней неточности математики с плавающей запятой.

Теперь , было два основных подхода к этой проблеме, метод грубой силы (который случайно сработал в этом случае, поскольку он каждый раз делал одни и те же ошибки) и более элегантный (который допускал разные ошибки и не работал). Любой, кто попробовал элегантный подход, ударил бы кирпичную стену, не имея любая идея почему. Я помог нескольким из них и вставил комментарий, объясняющий, почему, и чтобы связаться со мной, если у него возникнут вопросы.

Конечно, в следующем семестре я слышу от него об этом, и я, по сути, заполнил весь отдел простой небольшой программой:

10 X = 3000000
20 X = X + 1
30 If X < X + 1 goto 20
40 Print "X = X + 1"

] Несмотря на то, что думали все преподаватели кафедры, это БУДЕТ прекращено. 3 миллиона семян просто для того, чтобы ускорить его завершение. (Если вы не знаете основ: здесь нет уловок, просто исчерпывается точность чисел с плавающей запятой.)

) Любой, кто попробовал элегантный подход, ударился о кирпичную стену, даже не подозревая, почему. Я помог нескольким из них и вставил комментарий, объясняющий, почему, и чтобы связаться со мной, если у него возникнут вопросы.

Конечно, в следующем семестре я слышу от него об этом, и я, по сути, заполнил весь отдел простой небольшой программой:

10 X = 3000000
20 X = X + 1
30 If X < X + 1 goto 20
40 Print "X = X + 1"

] Несмотря на то, что думали все преподаватели кафедры, это БУДЕТ прекращено. 3 миллиона семян просто для того, чтобы ускорить его завершение. (Если вы не знаете основ: здесь нет уловок, просто исчерпывается точность чисел с плавающей запятой.)

) Любой, кто попробовал элегантный подход, ударился о кирпичную стену, даже не подозревая, почему. Я помог нескольким из них и вставил комментарий, объясняющий, почему, и чтобы связаться со мной, если у него возникнут вопросы.

Конечно, в следующем семестре я слышу от него об этом, и я, по сути, заполнил весь отдел простой небольшой программой:

10 X = 3000000
20 X = X + 1
30 If X < X + 1 goto 20
40 Print "X = X + 1"

] Несмотря на то, что думали все преподаватели кафедры, это БУДЕТ прекращено. 3 миллиона семян просто для того, чтобы ускорить его завершение. (Если вы не знаете основ: здесь нет уловок, просто исчерпывается точность чисел с плавающей запятой.)

10 X = 3000000
20 X = X + 1
30 If X < X + 1 goto 20
40 Print "X = X + 1"

Несмотря на то, что думали все учителя на кафедре, это БУДЕТ прекращено. 3 миллиона семян просто для того, чтобы ускорить его завершение. (Если вы не знаете основ: здесь нет уловок, просто исчерпывается точность чисел с плавающей запятой.)

10 X = 3000000
20 X = X + 1
30 If X < X + 1 goto 20
40 Print "X = X + 1"

Несмотря на то, что думали все учителя на кафедре, это БУДЕТ прекращено. 3 миллиона семян просто для того, чтобы ускорить его завершение. (Если вы не знаете основ: здесь нет уловок, просто исчерпывается точность чисел с плавающей запятой.)

4
ответ дан 29 November 2019 в 03:20
поделиться

да, Java также использует арифметику с плавающей запятой .

1
ответ дан 29 November 2019 в 03:20
поделиться

Конечно, это правда. Подумай об этом. Любое число должно быть представлено в двоичном формате.

Рисунок: «1000» как 0,5 или 1/2, то есть 2 ** -1. Тогда «0100» равно 0,25 или 1/4. Вы можете видеть, куда я иду.

Сколько чисел вы можете представить таким образом? 2 ** 4. Добавление дополнительных бит дублирует доступное пространство, но оно никогда не бывает бесконечным. 1/3 или 1/10, в данном случае 1 / n, любое число, не кратное 2.

1/3 может быть «0101» (0,3125) или «0110» (0,375). Любое значение, если вы умножите его на 3, не будет равно 1. Конечно, вы можете добавить специальные правила. Скажем, «когда вы добавляете 3 раза '0101', получается 1» ... этот подход не будет работать в долгосрочной перспективе. Вы можете поймать некоторые, но как насчет 1/6 умножить на 2?

Это не проблема двоичного представления,

2
ответ дан 29 November 2019 в 03:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: