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

Popular posts from this blog

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -