Вот ситуация: у меня есть вектор 0:4, который я использую log1p для преобразования и обратного преобразования с помощью exp(x) - 1. Я классифицировал исходный вектор 0:4 и вектор обратного преобразования, используя одни и те же критерии, но результаты различаются для Windows и Linux.
Ниже приведен минимальный пример, который я подготовил:
vec_original <- 0:4
log_vec <- log1p(vec_original)
vec_bktrans <- exp(log_vec) - 1
cat_original <- cut(vec_original, c(0, 1, 2, 4, Inf), include.lowest = TRUE)
cat_bktrans <- cut(vec_bktrans, c(0, 1, 2, 4, Inf), include.lowest = TRUE)
data.frame(
original = format(vec_original, digits = 20),
bk_trans = format(vec_bktrans, digits = 20),
cat_original = cat_original,
cat_bktrans = cat_bktrans
)
При запуске того же кода в Linux я получаю следующий результат (см. строку номер 3):
original bk_trans cat_original cat_bktrans
1 0 0.0000000000000000000 [0,1] [0,1]
2 1 1.0000000000000000000 [0,1] [0,1]
3 2 1.9999999999999995559 (1,2] (1,2]
4 3 3.0000000000000000000 (2,4] (2,4]
5 4 3.9999999999999991118 (2,4] (2,4]
В Windows я получаю следующие результаты (см. строку номер 3):
original bk_trans cat_original cat_bktrans
1 0 0.0000000000000000000 [0,1] [0,1]
2 1 1.0000000000000000000 [0,1] [0,1]
3 2 2.0000000000000004441 (1,2] (2,4]
4 3 3.0000000000000000000 (2,4] (2,4]
5 4 3.9999999999999991118 (2,4] (2,4]
Может ли кто-нибудь объяснить, в чем причина этого?
Я полагаю, что обходной путь — округлить окончательные значения до нескольких десятичных знаков, что имеет смысл в контексте вашего анализа. Я предполагаю, что 1,999999 и 2,000000, вероятно, теоретически одинаковы.
Чтобы ответить на вопрос «любое обходное решение», было бы полезно иметь больше контекста: какая часть вашего текущего кода/рабочего процесса ломается из-за того, что эти результаты не совсем совпадают?
Различные алгоритмы для вычисления значений, выполняющие разные вычисления, дают немного разные результаты?





Это предположение, но я предполагаю, что разница между платформами (которая может зависеть от деталей параметров компилятора и фактической архитектуры ЦП, а также ОС) связана с необязательным использованием где-то 80-битных регистров расширенной точности. в вычислительном пути, например. см. этот вопрос или этот вопрос . Гораздо больше информации о повышенной точности здесь:
Вышеизложенные замечания не направлены на принижение расширенных систем, а направлены на то, чтобы выявить несколько заблуждений, первое из которых состоит в том, что все системы IEEE 754 должны предоставлять одинаковые результаты для одной и той же программы.
... В результате, несмотря на почти повсеместное соответствие (большинству) стандарту IEEE 754 во всей компьютерной индустрии, программистам портативного программного обеспечения приходится продолжать справляться с непредсказуемой арифметикой с плавающей запятой.
Ответ более высокого уровня на этот вопрос (к сожалению) «никогда не полагайтесь на точное равенство в вычислениях с плавающей запятой на разных платформах». «Любым обходным путем» было бы округление результатов, как предлагает @thelatemail, или использование чего-то вроде all.equal() для проверки приблизительного равенства (точный ответ будет зависеть от того, какое использование вы хотите использовать в дальнейшем, и почему важно, чтобы они быть в точности эквивалентны...)
Да, я понял проблему с неточностями чисел с плавающей запятой в машинах, но в посте все еще не объясняются различия в Windows и Linux.