x86_64 程序集双重比较有时无法按预期工作
x86_64 Assembly double comparison not working as intended, some of the time
我知道浮点数不准确,但我需要一种解决方法。
所以,我需要做一个图遍历,我通过将所有节点放入堆栈,添加到所有邻居的路由,然后添加到所有非邻居的大路由,最后通过并找到最佳路线。它适用于从邻居创建的路由,但它在创建大量路由时中断。
这是相关的代码部分。
这里指定了大路由
movsd xmm0, [big]
mov [r11+rax+TAR], r9
movsd [r11+rax+DIS], xmm0
mov [r11+rax+HOP], r9
这里做对比,是为了看看有没有找到更好的路线。
ucomisd xmm0, xmm2
ja bMBD
jmp eMBD
bMBD:
mov rax, [r8+ROT]
mov [rax+r13+HOP], r11
movsd [rax+r13+DIS], xmm2
eMBD:
上面的代码块是问题所在,下面是我认为代码正在执行的分解。
D asks D for better route, but nothing happens: good.
D asks A, finds one and calculates distance as 3.3+5.4=8.7, it's better and replaces it's current route: good.
D asks B, finds one with a distance of 8.7+0=8.7. For some reason this is regarded as better and it's route is replaced: bad.
那么,为什么 ja
条件返回 8.7 > 8.7,但仅在将距离初始化为较大数字的路线上(我尝试减小数字的大小,但产生了相同的结果)?
谢谢。
四舍五入差异是浮点数学中的一个事实。这是解释 here.
如果你只需要找到任意条最佳路线,那么我看3.3 + 5.4 > 8.7 + 0.0
没问题;任何一条路线都可以。
如果您需要检索具有相同最佳距离的 所有 条路线,那么我同意您确实需要 3.3 + 5.4
等于 8.7 + 0.0
。
有几种方法可以做到这一点;见下文。对于示例代码,我将使用伪代码而不是汇编代码,因为这个问题不特定于任何语言。
1。忽略细微差别
如果数字之差的绝对值小于某个小数字(例如 0.001),则认为数字相等。
这意味着比较逻辑变得稍微复杂一些。
而不是:
if x < y then
return LESS_THAN
elseif x > y then
return GREATER_THAN
else
return EQUAL
你会做:
epsilon = 0.001
if x < y - epsilon then
return LESS_THAN
elseif x > y + epsilon then
return GREATER_THAN
else
return EQUAL
2。使用定点数
这比听起来容易;只需将所有内容乘以某个因子即可消除每个数字的小数部分,并根据整数而不是浮点数执行所有计算。
对于距离NNNN.N
(即小数点后不超过一位小数),该系数为10。
所以代替:
routeA = 3.3 + 5.4
routeB = 8.7 + 0.0
if routeA > routeB then ...
你会做:
routeA = 33 + 54
routeB = 87 + 0
if routeA > routeB then ...
我知道浮点数不准确,但我需要一种解决方法。
所以,我需要做一个图遍历,我通过将所有节点放入堆栈,添加到所有邻居的路由,然后添加到所有非邻居的大路由,最后通过并找到最佳路线。它适用于从邻居创建的路由,但它在创建大量路由时中断。
这是相关的代码部分。
这里指定了大路由
movsd xmm0, [big]
mov [r11+rax+TAR], r9
movsd [r11+rax+DIS], xmm0
mov [r11+rax+HOP], r9
这里做对比,是为了看看有没有找到更好的路线。
ucomisd xmm0, xmm2
ja bMBD
jmp eMBD
bMBD:
mov rax, [r8+ROT]
mov [rax+r13+HOP], r11
movsd [rax+r13+DIS], xmm2
eMBD:
上面的代码块是问题所在,下面是我认为代码正在执行的分解。
D asks D for better route, but nothing happens: good.
D asks A, finds one and calculates distance as 3.3+5.4=8.7, it's better and replaces it's current route: good.
D asks B, finds one with a distance of 8.7+0=8.7. For some reason this is regarded as better and it's route is replaced: bad.
那么,为什么 ja
条件返回 8.7 > 8.7,但仅在将距离初始化为较大数字的路线上(我尝试减小数字的大小,但产生了相同的结果)?
谢谢。
四舍五入差异是浮点数学中的一个事实。这是解释 here.
如果你只需要找到任意条最佳路线,那么我看3.3 + 5.4 > 8.7 + 0.0
没问题;任何一条路线都可以。
如果您需要检索具有相同最佳距离的 所有 条路线,那么我同意您确实需要 3.3 + 5.4
等于 8.7 + 0.0
。
有几种方法可以做到这一点;见下文。对于示例代码,我将使用伪代码而不是汇编代码,因为这个问题不特定于任何语言。
1。忽略细微差别
如果数字之差的绝对值小于某个小数字(例如 0.001),则认为数字相等。 这意味着比较逻辑变得稍微复杂一些。 而不是:
if x < y then
return LESS_THAN
elseif x > y then
return GREATER_THAN
else
return EQUAL
你会做:
epsilon = 0.001
if x < y - epsilon then
return LESS_THAN
elseif x > y + epsilon then
return GREATER_THAN
else
return EQUAL
2。使用定点数
这比听起来容易;只需将所有内容乘以某个因子即可消除每个数字的小数部分,并根据整数而不是浮点数执行所有计算。
对于距离NNNN.N
(即小数点后不超过一位小数),该系数为10。
所以代替:
routeA = 3.3 + 5.4
routeB = 8.7 + 0.0
if routeA > routeB then ...
你会做:
routeA = 33 + 54
routeB = 87 + 0
if routeA > routeB then ...