【发布时间】:2020-12-03 03:46:15
【问题描述】:
我能从 YouTube 视频中学到的是个位数的乘法或除法。
但是,如果我想计算多个带小数点的数字怎么办?
例如
输入1:123
输入2:320
计算 = 输入 1 x 输入 1 / 输入 2
答案为 47.28(实际答案为 47.278125,但转换为 2 个小数点)
谁能提供例子就好了。谢谢!
【问题讨论】:
标签: assembly x86 64-bit x86-64
我能从 YouTube 视频中学到的是个位数的乘法或除法。
但是,如果我想计算多个带小数点的数字怎么办?
例如
输入1:123
输入2:320
计算 = 输入 1 x 输入 1 / 输入 2
答案为 47.28(实际答案为 47.278125,但转换为 2 个小数点)
谁能提供例子就好了。谢谢!
【问题讨论】:
标签: assembly x86 64-bit x86-64
使用浮点单元 (FPU)。
这是您计算的精髓:
num1 dd 123
num2 dd 320
hundred dd 100
result dd 0
...
fild dword [num1] ; [st0] 123
fmul st0 ; [st0] 123 x 123 == 15129
fidiv dword [num2] ; [st0] (123 x 123) / 320 == 47.278125
fimul dword [hundred] ; [st0] ((123 x 123) / 320) * 100 == 4727.8125
fistp dword [result] ; floating point stack is empty
fimul dword [hundred] 指令的存在是为了在值被存储回主存储器时不会丢失 2 位小数。 fistp dword [result] 指令会将值四舍五入为最接近的整数。
结果现在包含 4728,您可以将其除以 100 以获得整数部分和 2 位小数:
mov eax, [result]
xor edx, edx
div dword [hundred] ; -> Quotient EAX == 47, Remainder EDX == 28
根据需要进一步处理这些。
【讨论】:
100.0 常量)。 SSE 没有像fidiv 这样转换和除以转换结果的指令;这是 x87 独有的。但是您可以直接从 double 转换为 EAX,而不需要 result 的内存空间。
处理小数值的一种方法是使用fixed-point 表示,这在各种情况下都很有用。例如,神经网络可以利用定点表示和权重量化到improve prediction speed 并减少存储需求。
在定点中,数字由整数和比例因子表示。例如,2.020 可以用整数2020 和比例因子1/1000 表示。使用为 2 的幂的缩放因子在计算上很方便,因为位移可用于重新缩放。对于某些操作,例如加法和减法,生成的比例因子与操作数的比例因子相匹配。对于乘法,缩放因子相乘,可以使用随后的除法(或位移)重新缩放。对于除法,缩放因子会被除掉,这可以通过对其中一个操作数进行缩放来解释。
例如,这是问题中示例的x86-64 程序集中的实现,这导致rax 中的47 和rbx 中的28。我相信按原样使用的除法(和右位移)会引入偏差,因为会有截断而不是舍入。下面的代码一般不处理这个问题,但是对于将小数四舍五入到两位数的情况(否则小数会截断为27)。在右位移之前添加1/2 将在重新缩放时result in rounding。将(divisor - 1) / 2 添加到股息将result in rounding 进行除法。但是,相对于其他错误源,截断 may be small 会产生错误。
mov rax, 123 ; rax = 123
imul rax, rax ; rax *= rax
shl rax, 8 ; use scaling factor of 2 ^ -8 for the numerator
mov rbx, 320 ; rbx = 320
xor rdx, rdx ; set numerator high bits to 0 for division
div rbx ; rax /= rbx
movzx ebx, al ; move fractional part from al to bl
shr rax, 8 ; rescale to unit scaling factor
imul rbx, 100 ; multiply leftmost two decimals out of fractional part
add rbx, 0x80 ; if fractional part > 1/2, carry into integer
shr rbx, 8 ; drop fraction from rbx
【讨论】: