In order to have exact geometric computations it is necessary to avoid the
issues of floating point arithmetic. CGAL can work with a range of different
exact kernels, where euclid uses the Exact_predicates_exact_constructions
predifined kernel. Moving values in and out of R would force a conversion to
double thus destroying the exactness of computation, so euclid provides a new
numeric vector class that simply maps to the underlying exact representation.
While the exact numeric class generally behaves as a standard numeric there
are operations that are not possible because it will loose the exactness,
e.g. trigonometric functions, roots, etc. If any unsupported function is
needed it is necessary to convert back to numeric (thus loosing exactness).
Anywhere euclid takes a numeric input it will convert it to an exact numeric
before use.
Usage
exact_numeric(x = numeric(0))
is_exact_numeric(x)
as_exact_numeric(x)
Note
Exact numeric only have one form of non-finite value: NA
. Any other
non-finite value will be converted to that.
See also
Other non-geometry vectors:
affine_transformation
,
bbox()
Examples
# Standard use
exact_numeric(runif(5))
#> <exact numerics [5]>
#> [1] 0.6097104 0.3787757 0.6900914 0.9322717 0.4997023
# Non-finite numbers are all converted to NA
exact_numeric(NaN)
#> <exact numerics [1]>
#> [1] NA
# this is also true for division by zero
exact_numeric(runif(5)) / 0
#> <exact numerics [5]>
#> [1] NA NA NA NA NA
# Exact numerics are more limited on operations but doesn't have the
# weirdness of floating point arithmetic:
float <- c(1, 2, 3)
identical(float[1] + float[2], float[3])
#> [1] TRUE
float <- float / 10
identical((float[1] + float[2]) * 10, float[3] * 10)
#> [1] FALSE
exact <- exact_numeric(c(1, 2, 3))
identical(as.numeric(exact[1] + exact[2]), as.numeric(exact[3]))
#> [1] TRUE
exact <- exact / 10
identical(as.numeric((exact[1] + exact[2]) * 10), as.numeric(exact[3] * 10))
#> [1] TRUE
# This only holds if the input are exact to begin with
identical(
as.numeric(exact_numeric(1/10 + 2/10)),
as.numeric(exact_numeric(3/10))
)
#> [1] FALSE