floating point - x86_64 Assembly double comparison not working as intended, some of the time -
i'm aware of floating point inaccuracies, need way around them.
so, need graph traversal, , i'm doing getting nodes stack, adding routes neighbors, adding large route non-neighbors, going through , finding best routes. works fine routes created neighbors, breaks on routes created large number.
here's relevant sections of code.
here large route assigned.
movsd xmm0, [big] mov [r11+rax+tar], r9 movsd [r11+rax+dis], xmm0 mov [r11+rax+hop], r9
here comparison made, in order see if better route found.
ucomisd xmm0, xmm2 ja bmbd jmp embd bmbd: mov rax, [r8+rot] mov [rax+r13+hop], r11 movsd [rax+r13+dis], xmm2 embd:
the above block of code problem is, following breakdown of believe code doing.
d asks d better route, nothing happens: good.
d asks a, finds 1 , calculates distance 3.3+5.4=8.7, it's better , replaces it's current route: good.
d asks b, finds 1 distance of 8.7+0=8.7. reason regarded better , it's route replaced: bad.
so, why ja
condition returning 8.7 > 8.7, on routes had distance initialized large number (i've tried reducing size of number, has yielded same results)?
thank you.
rounding differences fact of life in floating point math. explained here.
if need find any 1 of best routes, see no problem in 3.3 + 5.4 > 8.7 + 0.0
; either 1 of routes fine.
if need retrieve all routes share same optimal distance, agree need 3.3 + 5.4
equal 8.7 + 0.0
. there few ways accomplish this; see below. sample code, using pseudo code rather assembly, since issue not specific language.
1. ignore minor differences
consider numbers equal if absolute value of difference less small number (e.g. 0.001). means comparison logic becomes more complex. instead of:
if x < y return less_than elseif x > y return greater_than else return equal
you doing:
epsilon = 0.001 if x < y - epsilon return less_than elseif x > y + epsilon return greater_than else return equal
2. use fixed point numbers
this easier sounds; multiply factor eliminate fractional part of every number, , perform calculations based on integers rather floats.
for distances nnnn.n
(i.e. no more 1 decimal digit behind decimal point), factor 10.
so instead of:
routea = 3.3 + 5.4 routeb = 8.7 + 0.0 if routea > routeb ...
you doing:
routea = 33 + 54 routeb = 87 + 0 if routea > routeb ...
Comments
Post a Comment