在 x86 汇编中使用整数除法处理百分比
Posted
技术标签:
【中文标题】在 x86 汇编中使用整数除法处理百分比【英文标题】:Working with percentages using integer division in x86 assembly 【发布时间】:2019-05-20 22:27:28 【问题描述】:我正在使用 Assembly (x86) 并且正在使用百分比。我的问题是以下一个:
我有一些价值 total_sum
代表 100%。
我计算total_sum/100
得到代表1%的值:
xorl %edx, %edx
movl total_sum, %eax
movl $100, %ecx
divl %ecx
稍后在我的程序中,我使用这个除法的结果来计算其他值所代表的百分比。
使用计算器完成的示例计算(浮点数):
515代表100%,506代表百分之几?
515/100 = 5.15 506/5.15 = 98.25
这意味着:506 约占 515 的 98%。
不幸的是,使用汇编语言和整数运算,计算看起来像这样:
515/100 = 5 506/5 = 101
这意味着 506 代表 515 的 101%。
但是,我不希望结果 > 100%。
我试图使用第一个部门的%edx
中的值进行一些更正。但是,对%eax
进行四舍五入(如果%edx
表示小数点后的第一位为5 或更多,则递增)并没有多大帮助。
如何确保我不会得到大于 100% 的值?
【问题讨论】:
请包含将数字相加到 total_sum 中的代码,并包含一组示例值。根据描述,如果值不是太大,您可以将它们乘以 10 的某个幂,可能是 10,000 或 1,000,000,然后再进行适当的除法。 需要更多关于以后计算的信息。一般来说;除法会导致精度损失,因此您希望将所有除法推迟到尽可能晚 - 例如而不是早点做k = total/100
,晚点a = b*k
,你可能什么都不做,早点a = (b*total)/100
晚点。
@Brendan 我编辑了这个问题,因为我想我已经理解了 OP 想要问的问题。然而,问题比你想象的还要糟糕:OP 执行两次除法(均具有精度损失),而不是一次乘法和一次除法。
8086 还是 X86?他们不一样
(506*100) / 515 给你你想要的结果。整数除法不像连续实数那样工作。
【参考方案1】:
我完全编辑了您的问题,因为它不容易理解。我希望我完全理解了你的问题,而问题仍然是在问你想问什么。
您描述的问题实际上不是汇编语言问题,而是与任何可以进行整数运算的编程语言(如 C/C++、Java、Pascal 等)相关的问题。
因此我从您的问题中删除了x86
标签并添加了integer-division
标签。
以下尝试:
我试图使用第一个部门的
%edx
中的值进行一些更正。但是,四舍五入%eax
... 并没有太大帮助。
不会帮助你。让我们看看您稍后执行的第二个计算:
570/5 = 114 570/6 = 95 510/5 = 102 510/6 = 85
所以如果第一次除法的(校正后的)结果是 5,那么虽然 510
如果第一次除法的(校正后的)结果是 6,则值 570 将计算为 95%,尽管 570>515。
这意味着没有整数 one_percent
代表 1%,并且在执行操作 percentage = number / one_percent
时会给您正确的结果。
您唯一的机会是在程序结束时执行以下计算:
percentage = (100 * number) / total_sum
请注意,在使用整数算术时,操作的顺序确实几乎总是很重要。所以下面的计算不会给出与上面的计算相同的结果:
percentage = 100 * (number / total_sum)
使用汇编语言,您可以通过以下方式进行第一次计算:
mov $100, %edx
mov some_number, %eax
mull %edx
; Now (edx:eax) contains the 64-bit value (100*some_number)
mov total_sum, %ecx
divl %ecx
; Now eax contains the 32-bit value (100*some_number)/total_sum
【讨论】:
以上是关于在 x86 汇编中使用整数除法处理百分比的主要内容,如果未能解决你的问题,请参考以下文章