Большинство людей, изучающих компьютерное программирование, часто начинают с простых математических программ. Сложение и вычитание чисел должно быть относительно простым, верно?
Допустим, вы пытаетесь сравнить два числа в Java. Взгляните на следующий код:
double a = 0.7; double b = 0.9; double x = a + 0.1; double y = b - 0.1; if (x == y) { System.out.println("x and y are the same!"); } else { System.out.println("x and y are not the same :("); }
Давайте сначала проработаем это мысленно. Переменная x равна a + 0,1. Переменная y равна b -0,1. Поскольку a равно 0,7, x должно равняться 0,8. А поскольку b равно 0,9, y также должно быть равно 0,8.
В этом примере x и y должны быть равны друг другу.
Тем не менее, это не так. Давайте углубимся в то, почему это происходит.
После того, как вы распечатаете x и y, вы обнаружите следующее.
x = 0.7999999999999999 y = 0.8
Хорошо… это выглядит правильно. 0,7999999999999 очень близко к 0,8. Ну, что здесь пошло не так?
Проблема здесь заключается в том, как десятичные числа хранятся в компьютерах. Компьютер использует основание 2 (двоичная система счисления) вместо традиционной системы с основанием 10.
В основе 10 у нас есть разряд единиц, разряд десятков, разряд сотых и так далее. Однако в базе 2 у нас есть разряд единиц, разряд двоек, разряд четверок, разряд восьмерок и так далее. Так что, если мы хотим представить 5 по основанию 2, нам нужна 1 в разряде четверок и 1 в разряде единиц, или «101».
Хорошо, тогда как мы представляем десятичные дроби? Как и в научной записи, вместо ЧИСЛО* 10^X мы можем использовать ЧИСЛО*2^Х для основания 2. Идя наоборот, теперь у нас есть один половинный разряд, один четверть разряд, один восьмой разряд и так далее. на.
Поэтому, если нам нужно представить 0,5 в двоичном виде, мы можем сделать это с помощью 0,1 (например, 1 * 2 ^-1). Если нам нужно представить 0,25 в двоичном виде, мы можем сделать это с помощью 0,01 (например, 1*2^-2).
Но время от времени вы получаете число, которое невозможно представить с помощью этой кодировки.
В нашем первом примере мы добавили число 0,1. В двоичном виде это число можно записать как 0,00011 повторений. Точно так же в базе 10 дробь 1/3 записывается как 0,33333 повторения. Математически это эквивалентно, но у компьютеров нет бесконечной памяти для повторения десятичных дробей. В конечном итоге это приводит к (хотя и несколько небольшой) потере точности.
Я не специалист и могут быть ошибки. Если вы заметили что-то не так с моим сообщением в блоге, сообщите мне, и я буду рад исправить любые проблемы :). Я закончил этот пост в блоге для университетского курса.