Как вы заметили, вы столкнулись с проблемой около нуля.Корни как числителя, так и знаменателя равны нулю.И, как упоминалось в ОП, используя L'Hôpitcal, вы замечаете, что в этом f (x) = 1/2 .
С числовой точки зрения все идет немного иначе.С плавающей запятой всегда будет ошибка, поскольку не каждое действительное число может быть представлено как число с плавающей запятой.Например:
exp(1E-3) -1 = 0.0010005001667083845973138522822409868 # numeric
exp(1/1000)-1 = 0.001000500166708341668055753993058311563076200580... # true
^
Проблема численной оценки exp(1E-3)-1
уже начинается с начала, т. Е. 1E-3
1E-3 = x = 0.0010000000000000000208166817117216851
exp(x) = 1.0010005001667083845973138522822409868
exp(x) - 1 = 0.0010005001667083845973138522822409868
1E-3
не может быть представлена какс плавающей запятой, с точностью до 17 цифр. - IEEE даст наиболее близкое возможное значение с плавающей запятой к истинному значению x, которое уже имеет ошибку из-за (1).Тем не менее,
exp(x)
имеет точность только до 17 цифр. - Вычитая 1, мы получаем кучу нулей в начале, и теперь наш результат точен только до 14 цифр.
Итак, теперь, когда мы знаем, что мы не можем представить все в точности как число с плавающей запятой, вы должны понимать, что около нуля становится немного неловко, а числитель и знаменатель становятся все менее и менее точными, особенно около 1E-13.
numerator_numeric(1E-13) = 1.1102230246251565E-16
numerator_true(1E-13) = 5.00000000000033333333333...E-27
Обычно, что вы делаете около такой точки, это использование разложения Тейлора около нуля, а обычная функция везде:
betaFun = function(x){
if(-1E-1 < x && x < 1E-1){
return(0.5 + x/12. - x^3/720. + x^5/30240.)
}
return( ( 1+exp(x)*(x-1) )/( x*(exp(x)-1) ) )
}
Вышеупомянутое расширение с точностью до 13 цифр для х вмаленький регион