Kotlin double больше, чем float - PullRequest
1 голос
/ 09 марта 2020

Я столкнулся с проблемой, которая меня интересовала, является ли ожидаемое поведение правильным или я нашел ошибку.

Учитывая это:

0.08 > 0.08 == false
0.08 > 0.08F == true
0.08 > 0.08F.toDouble() == true

0.08.toFloat() > 0.08F == false

Почему третье выражение не является ложный? Есть идеи?

Ответы [ 2 ]

3 голосов
/ 09 марта 2020

Это дополнение к существующему ответу . Java BigDecimal имеет два полезных свойства для анализа поведения с плавающей запятой. Преобразование из float или double в BigDecimal является точным, как и преобразование строк по умолчанию. Простейшее использование этих свойств - вывести точное значение выражения с плавающей запятой. BigDecimal arithmeti c также можно использовать, например, для поиска промежуточных точек между double и его соседями при изучении округления.

Эта программа:

import java.math.BigDecimal;

public strictfp class Test {
    public static void main(String[] args) {
        System.out.println(new BigDecimal(0.08));
        System.out.println(new BigDecimal(0.08f));
    }
}

output:

0.08000000000000000166533453693773481063544750213623046875
0.07999999821186065673828125

, что подтверждает, что 0,08 представляется с ожидаемой точностью в каждом формате, а представление double строго больше, чем float.

3 голосов
/ 09 марта 2020

Это не ошибка, она основана на ошибках округления.

Выполнение следующего кода:

val d = 0.08
val f = 0.08F
val fd = f.toDouble()
print("%.20f".format(d) + "\n")
print("%.20f".format(f) + "\n")
print("%.20f".format(fd))

дает следующий вывод:

0.08000000000000000000
0.07999999821186066000
0.07999999821186066000

Итак, как вы можете видеть, двойное значение 0,08 (с точностью до 20-го знака после запятой) точно равно 0,08, в то время как число с плавающей точкой (из-за более низкой точности) не может быть представлено как точное значение, поэтому оно содержит округленное значение, которое немного ниже 0,08.

Преобразование вашего приблизительного (немного меньшего) 0,08 с плавающей запятой в двойное не увеличивает вашу точность, у вас все еще есть ошибка округления с плавающей запятой, в результате чего конвертированный двойник будет немного ниже.

// Редактировать: Если вас интересует, как именно работают числа с плавающей запятой, я бы порекомендовал вам взглянуть на статью википедии об арифметике с плавающей запятой c и на вопрос: Математика с плавающей запятой не работает?

...