Возможный дубликат:
Почему эти цифры не равны?
0.9 == 1-0.1 >>> TRUE
0.9 == 1.1-0.2 >>> FALSE
Возможный дубликат:
Почему эти цифры не равны?
0.9 == 1-0.1 >>> TRUE
0.9 == 1.1-0.2 >>> FALSE
> all.equal(0.9,1.1-0.2)
[1] TRUE
> all.equal(0.9, 1.1-0.3)
[1] "Mean relative difference: 0.1111111"
> isTRUE(all.equal(0.9, 1.1-0.3)
[1] FALSE
и если используется в коде:
if(isTRUE(all.equal(0.9,1.1-0.2)) {
....
}
или в векторах:
> vec1=0.9
> vec2=c(1.1-0.2,1.3-0.4,1.0-0.2)
> mapply(function(...)isTRUE(all.equal(...)),vec1, vec2)
[1] TRUE TRUE FALSE
Я рекомендую вам прочитать " то, что должен знать каждый компьютерный ученый о числах с плавающей запятой". (или здесь).
Также Ричи указывает, что R faq упоминает эту проблему. Вы действительно должны прочитать весь FAQ R.
Проблема, с которой вы столкнулись, заключается в том, что плавающая точка не может представлять десятичные дроби точно в большинстве случаев, что означает, что вы часто обнаружите, что точные совпадения терпят неудачу.
в то время как R слегка лежит, когда вы говорите:
> 1.1-0.2
[1] 0.9
> 0.9
[1] 0.9
Вы можете узнать, что он на самом деле думает в десятичной форме:
> sprintf("%.54f",1.1-0.2)
[1] "0.900000000000000133226762955018784850835800170898437500"
> sprintf("%.54f",0.9)
[1] "0.900000000000000022204460492503130808472633361816406250"
Вы можете видеть, что эти цифры разные, но представление немного громоздко. Если мы посмотрим на них в двоичном (ну, шестнадцатеричный, что эквивалентно), мы получим более четкое изображение:
> sprintf("%a",0.9)
[1] "0x1.ccccccccccccdp-1"
> sprintf("%a",1.1-0.2)
[1] "0x1.ccccccccccccep-1"
> sprintf("%a",1.1-0.2-0.9)
[1] "0x1p-53"
Вы можете видеть, что они отличаются 2^-53
, что важно, потому что это число является наименьшей представляемой разницей между двумя числами, значение которых близко к 1, так как это.
Мы можем узнать для любого данного компьютера, что это наименьшее представимое число, просмотрев поле машинного поля R:
> ?.Machine
....
double.eps the smallest positive floating-point number x
such that 1 + x != 1. It equals base^ulp.digits if either
base is 2 or rounding is 0; otherwise, it is
(base^ulp.digits) / 2. Normally 2.220446e-16.
....
> .Machine$double.eps
[1] 2.220446e-16
> sprintf("%a",.Machine$double.eps)
[1] "0x1p-52"
Этот факт можно использовать для создания функции "почти равных", которая проверяет, что разница близка к наименьшему представимому числу в плавающей запятой. На самом деле это уже существует (спасибо комментатору).
> ?all.equal
....
all.equal(x,y) is a utility to compare R objects x and y testing ‘near equality’.
....
all.equal(target, current,
tolerance = .Machine$double.eps ^ 0.5,
scale = NULL, check.attributes = TRUE, ...)
....
> all.equal(0.9,1.1-0.2)
[1] TRUE
Таким образом, функция all.equal фактически проверяет, что разница между числами является квадратным корнем из наименьшей разницы между двумя мантиссами.
Этот алгоритм выглядит немного смешно вблизи чрезвычайно маленьких чисел, называемых денормалами, но вам не нужно об этом беспокоиться.
Вам нужно быть осторожным в программировании, когда вы хотите проверить, не вычисленны два числа равны. R будет предполагать, что вы имеете в виду "ровно равные", и что это означает зависит от точности машины. Большинство номеров округлены до 53 двоичных цифр. Как правило, поэтому два числа с плавающей запятой не будут надежно равны, если они не были вычисленный по тому же алгоритму, и не всегда даже тогда. Вы можете видеть это путем возведения в квадрат квадратный корень из 2: эти значения одинаковы?
x <- sqrt(2)
x * x == 2
[1] FALSE
Мы можем видеть, насколько эти два значения отличаются вычитанием:
1.1 - 0.2 - 0.9
[1] 1.110223e-16