如何使用Irvine32 WriteFloat(而不是printf)显示四舍五入为.001的浮点数 [英] How to display floating-point rounded to .001 with Irvine32 WriteFloat, not printf

查看:55
本文介绍了如何使用Irvine32 WriteFloat(而不是printf)显示四舍五入为.001的浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对汇编语言非常陌生,所以请耐心等待...

I am very new to assembly language so bear with me...

我有一个四舍五入到最接近的.001的浮点,但仍显示为+ 1.6670000E + 000.我希望它显示为1.667.

I have a floating-point that I have rounded to the nearest .001, but still displays as something like +1.6670000E+000. I would like it to display simply as 1.667.

这是我的数字除法和四舍五入代码:

Here is my code for dividing and rounding the numbers:

fild    num_a
fidiv   num_b
fimul   thousand
frndint
fidiv   thousand
fst     a_div_b

这是我显示浮动的代码:

And here is my code for displaying the float:

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库.

I looked a lot online and there were many answers on how to round numbers, but they still all displayed in the extended format. I am using the irvine32 library.

推荐答案

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

An even a simpler modification to the approach discussed in comments:

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

Multiply by 1000 and convert that to integer with fistp (with the default rounding to nearest), instead of just rounding to an integer-valued long double using frndint.

该整数的低3个小数位是数字的小数部分.,即您现在有了十进制定点. div 乘以1000可得到商(整数部分)和余数(小数部分).打印两个部分,并在它们之间使用..

The low 3 decimal digits of that integer are the fractional part of your number. i.e. you now have decimal fixed-point. div by 1000 gives you quotient (integer part) and remainder (fractional part). Print both parts with a . between them.

您需要手动进行int->字符串转换(

You'll want to do manual int->string conversion (How do I print an integer in Assembly Level Programming without printf from the c library?) or otherwise print leading zeros in the fractional part. (So 2.062 doesn't turn into 2.62)

这比在FP中分成整数和小数部分要容易得多,在FP中,整数和小数部分需要四舍五入为零,以确保您得到非负的小数部分.整数除法自然会截断为零,但是传统的x87 FP-> int转换只能使用默认的舍入模式.(除了SSE3 .)自引入以来,SSE1/2具有带有截断或当前舍入模式的XMM FP-> int转换,例如 cvttsd2si vs. cvtsd2si

This is easier than separating into integer and fractional parts in FP, which would require rounding with truncation toward zero to make sure you got a non-negative fractional part. Integer division naturally truncates towards zero, but legacy x87 FP->int conversion can only use the default rounding mode. (Except with SSE3 fisttp.) SSE1/2 had XMM FP->int conversions with truncation or current rounding mode since they were introduced, like cvttsd2si vs. cvtsd2si

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

Downside: overflows a 32-bit integer for smaller float inputs, because a single 32-bit integer has to hold x * 1000.

另一种方法是使用 x - (int)x 得到小数部分,并且只将 那个 小数部分乘以 1000.0.这导致(int)x 与小数部分形成单独的整数,其中 x * 1000 仅作为浮点存在,而不存在 int32_t

The other way is to use x - (int)x to get the fractional part and only multiplying that fractional part by 1000.0. That leads to (int)x in a separate integer from the the fractional part, with x*1000 only existing as floating point, not int32_t.

有趣的事实:

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

AVX512DQ has an instruction for getting the fractional part directly: VREDUCESD xmm1, xmm2, xmm3/m64, imm8 (and ss/ps/pd versions). It's the part that SSE4 roundsd / vrndscalesd would discard when keeping the integer part. Even more fun: can keep a specified number of fraction bits. But of course those are binary fraction bits, not decimal places.

如今,大多数x86 CPU具有SSE4.1,但只有Skylake-X高端台式机和现代Xeon具有AVX512DQ.:/和Ice Lake笔记本电脑.

Most x86 CPUs have SSE4.1 these days, but only Skylake-X high-end desktops and modern Xeons have AVX512DQ. :/ And Ice Lake laptops.

这篇关于如何使用Irvine32 WriteFloat(而不是printf)显示四舍五入为.001的浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆