Как уже говорили другие, это просто фундаментальная проблема, с которой вы сталкиваетесь при выполнении арифметических операций с плавающей запятой с любой базой. Просто так получилось, что base-2 является наиболее распространенным в компьютерах (потому что допускает эффективную аппаратную реализацию).
Лучшее исправление, если возможно, - это переключиться на использование некоторого частного представления числа для вашего цикла, сделав на основе этого значение с плавающей запятой. Хорошо, это звучит преувеличенно! Для вашего конкретного случая я бы написал это как:
int dTimes10 = 20;
double d;
while(dTimes10 != 0) {
dTimes10 -= 2;
d = dTimes10 / 10.0;
}
Здесь мы действительно работаем с дробями [20/10, 18/10, 16/10, ..., 2/10, 0/10], где итерация выполняется с целыми числами (т.е. легко получить правильные значения) в числитель с фиксированным знаменателем перед преобразованием в числа с плавающей запятой. Если вы можете переписать свои настоящие итерации так, чтобы они работали таким образом, вы добьетесь большого успеха (и в любом случае они не намного дороже, чем то, что вы делали раньше, что является отличным компромиссом. чтобы получить правильность).
Если вы не можете этого сделать, вам нужно использовать для сравнения равенство внутри эпсилона. Примерно это замена d != target
на abs(d - target) < ε
, где выбор ε (эпсилон) иногда может быть неудобным. По сути, правильное значение ε зависит от множества факторов, но, вероятно, лучше всего выбрать 0,001 для примера итерации с учетом масштаба значения шага (т. Е. Это половина процента от величины шага, поэтому все, что в пределах этого будет ошибкой, а не информативной).
person
Donal Fellows
schedule
28.07.2010
==
с плавающими значениями. Может, использовать что-нибудь вродеf>epsilon
. - person pascal   schedule 28.07.2010strictfp
не поможет. Это проблема, присущая всем числам с плавающей запятой, независимо от размера или точности. Единственный способ обойти это - использовать базу, отличную от 2, для экспоненты, и я не знаю ни одной реализации, которая это делает. - person cHao   schedule 28.07.2010