Hejsa,
Jeg er rendt ind i nogle problemer vedrørende nogle floating point
beregninger. Kort sagt går det ud på, at jeg skal tegne en cirkel med radius
R, der udfyldes med farve ved at tegne cirkler med radius 0 < r_i < R for i
= 1,...,mange så man opnår illusion om et kontinuert farvelag.
Jeg har en funktion f(x;p) = +/- sqrt(-x^2 - 2*ln(1-p)), 0 < p < 1 og 0 < x
<= R som er en cirkel med radius R = sqrt(-2*ln(1-p)).
Programmet, R, som jeg bruger til udregningerne har en begrænset
nøjagtighed, og dette giver vi problemer i de mange udregninger. Visse
værdier af x, når x nærmer sig R, fejler (da resultatet bliver imaginært)
pga. decimalfejl.
Her er et eksempel, der belyser problemet
> f <-function(x,p)sqrt(-(x^2)-2*log(1-p))
> r1 <-sqrt(-2*log(1-0.95))
> r2 <-sqrt(-2*log(0.05))
> f(r1, 0.95)
> [1] 0
> f(r2, 0.95)
> [1] NaN
> Warning message:
> NaNs produced in: sqrt(-(x^2) - 2 * log(1 - p))
Begge udregninger burde selvfølgelig give 0 stringent set. Hvis vi kigger på
logaritmen, der benyttes i eksemplet, ses følgende:
> print(log(0.05),digit=22)
[1] -2.9957322735539909
> print(log(1-0.95),digit=22)
[1] -2.99573227355399
Som det ses, er der forskel på de 2 sidste decimaler, og derfor giver
log(1-0.95) og log(0.05)forskellige resultater, som kan give fejl. F.eks.
som i ovenstående.
Hvad gør man i den slags situationer? Er der et lille maskinafhængigt tal,
epsilon, som man kan trække fra/lægge til kritiske værdier, så man er sikker
på, at de ikke fejler?
Der findes en konstant double.eps: the smallest positive floating-point
number 'x' such that '1 + x != 1'. Kan jeg bruge det til noget?
Ellers er der følgende konstanter til rådighed
> .Machine
$double.eps
[1] 2.220446e-16
$double.neg.eps
[1] 1.110223e-16
$double.xmin
[1] 2.225074e-308
$double.xmax
[1] 1.797693e+308
$double.base
[1] 2
$double.digits
[1] 53
$double.rounding
[1] 5
$double.guard
[1] 0
$double.ulp.digits
[1] -52
$double.neg.ulp.digits
[1] -53
$double.exponent
[1] 11
$double.min.exp
[1] -1022
$double.max.exp
[1] 1024
$integer.max
[1] 2147483647
$sizeof.long
[1] 4
$sizeof.longlong
[1] 8
$sizeof.longdouble
[1] 12
$sizeof.pointer
[1] 4
På forhånd tak,
Christian
xpost til dk.videnskab med follow-up-to dk.edb.programmering.
|