首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Irvine32 WriteFloat而不是printf显示四舍五入为.001的浮点数

如何使用Irvine32 WriteFloat而不是printf显示四舍五入为.001的浮点数
EN

Stack Overflow用户
提问于 2020-04-04 05:39:16
回答 1查看 550关注 0票数 0

我对汇编语言很陌生,所以请耐心听我说…

我有一个四舍五入到最近的.001的浮点数,但仍然显示为类似于+1.6670000E+000的内容。我希望它简单地显示为1.667。

下面是我对数字进行除法和舍入的代码:

代码语言:javascript
复制
fild    num_a
fidiv   num_b
fimul   thousand
frndint
fidiv   thousand
fst     a_div_b

下面是我用来显示浮动的代码:

代码语言:javascript
复制
mov     eax, num_a
call    WriteDec
mov     edx, OFFSET divide
call    WriteString
mov     eax, num_b
call    WriteDec
mov     edx, OFFSET equals
call    WriteString
fld     a_div_b
call    WriteFloat
call    CrLf

我在网上看了很多,有很多关于如何对数字进行舍入的答案,但它们仍然以扩展格式显示。我正在使用irvine32库。

EN

回答 1

Stack Overflow用户

发布于 2020-04-04 07:16:28

对注释中讨论的方法进行了更简单的修改:

乘以1000并使用fistp将其转换为整数(默认舍入为最接近),而不是使用frndint仅舍入为整数值long double

这个整数的低3位小数是你的数字的小数部分。,即你现在有了小数定点。div乘以1000得到商(整数部分)和余数(小数部分)。打印两部分,中间有一个 .

您需要手动执行int->string转换(How do I print an integer in Assembly Level Programming without printf from the c library?),或者在小数部分打印前导零。(这样2.062就不会变成2.62)

这比在FP中分成整数和小数部分更容易,后者需要舍入并截断到零,以确保得到非负的小数部分。整数除法自然会向零截断,但传统的x87 FP->int转换只能使用默认的舍入模式。( SSE3 fisttp除外。)自引入以来,SSE1/2具有带有截断或当前舍入模式的XMM FP->int转换,就像cvttsd2sicvtsd2si一样

的缺点:对于较小的浮点输入,溢出32位整数,因为单个32位整数必须保存x * 1000

另一种方法是使用x - (int)x获得小数部分,并仅将该小数部分乘以1000.0。这导致(int)x与小数部分分开,x*1000只作为浮点存在,而不是int32_t

有趣的事实:

AVX512DQ有一个直接获取小数部分的指令:VREDUCESD xmm1, xmm2, xmm3/m64, imm8 (和ss/ps/pd版本)。这是SSE4 roundsd / vrndscalesd在保留整数部分时会丢弃的部分。更有趣的是:可以保留指定数量的分数位。当然,这些是二进制分数位,而不是十进制位。

如今,大多数Skylake CPU都有AVX512DQ 4.1,但只有Skylake-X高端台式机和现代至强CPU有SSE4.1。:/和冰湖笔记本电脑。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61020815

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档