기계 정밀도 double
는 현재 값 에 따라 다릅니다. .Machine$double.eps
값이 1 인 경우 정밀도를 제공합니다. C 함수 nextAfter
를 사용하여 다른 값의 기계 정밀도를 얻을 수 있습니다.
library(Rcpp)
cppFunction("double getPrec(double x) {
return nextafter(x, std::numeric_limits<double>::infinity()) - x;}")
(pr <- getPrec(1))
#[1] 2.220446e-16
1 + pr == 1
#[1] FALSE
1 + pr/2 == 1
#[1] TRUE
1 + (pr/2 + getPrec(pr/2)) == 1
#[1] FALSE
1 + pr/2 + pr/2 == 1
#[1] TRUE
pr/2 + pr/2 + 1 == 1
#[1] FALSE
값을 추가 a
값은 b
변경되지 않습니다 b
때 a
입니다 <=
그것의 기계 정밀도의 절반. 차이가 기계 정밀도보다 작은 지 확인하십시오 <
. 수정자는 추가가 변경을 표시하지 않은 일반적인 경우를 고려할 수 있습니다.
에서 R 기계의 정밀도로 추정 할 수있다 :
getPrecR <- function(x) {
y <- log2(pmax(.Machine$double.xmin, abs(x)))
ifelse(x < 0 & floor(y) == y, 2^(y-1), 2^floor(y)) * .Machine$double.eps
}
getPrecR(1)
#[1] 2.220446e-16
각 double
값은 범위를 나타냅니다. 간단한 추가를 위해 결과 범위는 각 소환의 범위와 합계의 범위에 따라 다릅니다.
library(Rcpp)
cppFunction("std::vector<double> getRange(double x) {return std::vector<double>{
(nextafter(x, -std::numeric_limits<double>::infinity()) - x)/2.
, (nextafter(x, std::numeric_limits<double>::infinity()) - x)/2.};}")
x <- 2^54 - 2
getRange(x)
#[1] -1 1
y <- 4.1
getRange(y)
#[1] -4.440892e-16 4.440892e-16
z <- x + y
getRange(z)
#[1] -2 2
z - x - y #Should be 0
#[1] 1.9
2^54 - 2.9 + 4.1 - (2^54 + 5.9) #Should be -4.7
#[1] 0
2^54 - 2.9 == 2^54 - 2 #Gain 0.9
2^54 - 2 + 4.1 == 2^54 + 4 #Gain 1.9
2^54 + 5.9 == 2^54 + 4 #Gain 1.9
더 높은 정밀도 Rmpfr
를 위해 사용될 수있다.
library(Rmpfr)
mpfr("2", 1024L)^54 - 2.9 + 4.1 - (mpfr("2", 1024L)^54 + 5.9)
#[1] -4.700000000000000621724893790087662637233734130859375
정수로 변환 할 gmp
수있는 경우 (Rmpfr에있는) 사용할 수 있습니다.
library(gmp)
as.bigz("2")^54 * 10 - 29 + 41 - (as.bigz("2")^54 * 10 + 59)
#[1] -47