C printf浮点数 [英] C printf float rounding

查看:184
本文介绍了C printf浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须使用 C 重新实现 printf(3),而不使用任何对我进行转换的函数

I have to reimplement printf(3) with C without using any function that would do the conversion for me.

我几乎完成了,我只需要%a ,而且几乎完成了你们: a href =https://stackoverflow.com/questions/29143651/how-a-conversion-work-in-printf-statement>在printf语句中有多少转换工作?

I'm nearly done I just need %a and it's also nearly done thanks to you guys : How %a conversion work in printf statement?

该人说:


双参数是四舍五入并转换为十六进制符号
在样式[ - ] 0xh.hhhp [+ - ] d,其中
后的数字的十六进制点字符等于精度规范。

The double argument is rounded and converted to hexadecimal notation in the style[-]0xh.hhhp[+-]d, where the number of digits after the hexadecimal-point character is equal to the precision specification.

所以我的问题是圆角

我发现: printf四舍五入的行为

它解释了printf我使用银行家回合或一半到偶数,但我不知道如何实现我已经尝试过:

And it explains that printf is using banker round or Round half to even but I have no idea how to implement it I have tried this:

a_double = round(a_double * pow(10, precision)) / pow(10, precision)

但是从 0.000001 开始 1000000 测试,并添加 0.000001 每次失败 405201 次,例如使用 0.000011

But on 1000000 tests starting from 0.000001 and adding 0.000001 each time it fails 405201 times, for example with 0.000011:

printf("%.6a", 0.000011) => 0x1.711948p-17
myprintf("%.6a", 0.000011) => 0x1.711947p-17

舍入失败,我没有得到与真正的printf。

The rounding 'failed' and I didn't get the same value as the real printf.

我不认为将 double 转换为六进制符号是错误的,因为精确度 13 我绝对没有错误。

I don't think that the algorithm that transforms the double to hexa notation is wrong because with a precision of 13 I have absolutely no errors.

所以我只想知道如何我可以在 double printf c $ c>。

So I just would like to know how I could do the same rounding that printf does on the double.

推荐答案

好的,所以我想我以前的算法没有完全实现四舍五入,所以让我们来看看结果可以四舍五入。我将使用你的示例编号作为我的示例编号。首先,我们发现0.000011 /(2 ^( - 17))= 0.000011 *(2 ^ 17)= 1.441792,因此功率为-17。然后,我们输出1.,从1.441792减1,乘以16,给出7.068672。我们输出7,从中减去7,乘以16,给出1.09875199999999。我们输出1,从中减去1,乘以16,给出1.58003199999985。我们输出1,从中减去1,乘以16,给出9.28051199999754。然后输出9,减9,乘以16,结果为4.48819199996069。我们输出4,减4,乘以16,结果为7.81107199937105。

Ok, so I guess my previous algorithm didn't fully implement rounding so let's take a look how the result could be rounded. I'll use your example number as my example number too. First, we find that 0.000011/(2^(-17)) = 0.000011*(2^17) = 1.441792 so the power is -17. Then, we output "1.", subtract 1 from 1.441792 and multiply it by 16, giving 7.068672. We output 7, subtract 7 from it and multiply by 16, giving 1.09875199999999. We output 1, subtract 1 from it and multiply by 16, giving 1.58003199999985. We output 1, subtract 1 from it and multiply by 16, giving 9.28051199999754. Then output 9, subtract 9, multiply by 16, the result is 4.48819199996069. We output 4, subtract 4, multiply by 16, the result is 7.81107199937105.

现在,我们要输出最后一个字符。现在我们做魔术因为7.81107199937105比8更接近8,所以输出8。这个魔法只适用于最后一个角色。对于非最后一个字符,总是使用积分部分,并且在确定要输出哪个字符时根本不使用小数部分。然后,在此之后,我们输出p-17,因为权力是-17。

Now, we're going to output the last character. Now we do the magic. Because 7.81107199937105 is closer to 8 than to 7, we output "8". This magic is done only for the last character. For the non-last characters, the integral part is always used and the fractional part is not used at all in determining which character to output. Then, after this, we output "p-17" because the power was -17.

请注意,通常的四舍五入规则表示7.5与7相同而8是四舍五入到8,而不是7和6.5将被舍入到7,而不是6。但是,如果你想实现一半到偶数,你遇到例如6.5然后它被舍入到6,因为6是偶数,7不是。我不知道你发现银行家的回合是否也适用于%a,唯一可以做的是测试实现各种舍入算法,并查看与printf的真实%a相同的结果。不应该那么难,因为不同的舍入算法对于处理一半是不同的。其余的是四舍五入到最接近的数字。

Note that the usual rounding rules say that 7.5 which is equally close to both 7 and 8 is rounded to 8, not to 7 and 6.5 would be rounded to 7, not to 6. However, if you want to implement the round half to even and you encounter e.g. 6.5 then it is rounded down to 6 because 6 is even and 7 is not. I'm not sure if what you found about the banker round applies also to %a, the only thing you can do is to test implementing various rounding algorithms and see which gives the same results as the real %a of printf. Shouldn't be that hard because the different rounding algorithms just differ on how half is handled. The rest is rounded to the closest number.

顺便说一句,我在你之前的问题(在printf语句中转换工作的百分比如何?)说,对于具有非整数表示的3.2。1.999999 .... p +1和舍入表示1.99999ap + 1由于浮点精度有限,最后一个a将发生。当然,这是因为四舍五入而不是由于浮点精度有限,因为您现在可能已经意识到。

By the way, I was wrong in your previous question (How %a conversion work in printf statement?) in saying that for 3.2 which has the non-rounded representation 1.999999....p+1 and the rounded representation 1.99999ap+1 the last "a" would occur due to limited floating point precision. Of course it occurs due to rounding and not due to limited floating point precision, as you probably have realized by now.

这篇关于C printf浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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