我必须使用printf(3)
重新实现C
,而无需使用任何对我来说可以进行转换的函数。
我快完成了,我只需要%a
,也快完成了,谢谢你们:How %a conversion work in printf statement?
那人说:
将double参数四舍五入并转换为十六进制表示法
样式为[-] 0xh.hhhp [+-] d,其中后面的位数
十六进制点字符等于精度规格。
那么我的问题是如何四舍五入的呢?
我发现:printf rounding behavior for doubles
它说明了printf正在使用banker round或Round half来达到偶数,但是我不知道如何实现它,我已经尝试过了:
a_double = round(a_double * pow(10, precision)) / pow(10, precision)
但是在
1000000
测试中,从0.000001
开始并在每次失败0.000001
次(例如,使用405201
)时添加0.000011
:printf("%.6a", 0.000011) => 0x1.711948p-17
myprintf("%.6a", 0.000011) => 0x1.711947p-17
四舍五入“失败”,我没有得到与真实printf相同的值。
我不认为将
double
转换为hexa notation
的算法是错误的,因为精度为13
的我绝对没有错误。因此,我只想知道如何在
printf
上进行与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。
现在,我们将输出最后一个字符。现在我们做魔术。因为7.81107199937105比8更接近于8,所以我们输出“ 8”。此魔术仅适用于最后一个角色。对于非最后一个字符,在确定要输出哪个字符时,始终使用整数部分,而根本不使用小数部分。然后,在此之后,因为功率为-17,所以我们输出“ p-17”。
请注意,通常的舍入规则说,将与7和8均相等的7.5舍入为8,而不是7和6.5会舍入为7,而不是6。但是,如果要实现舍入一半为偶数而你遇到例如6.5然后将其舍入为6,因为6是偶数,而7不是。我不确定您对银行家回合的发现是否也适用于%a,您唯一能做的就是测试实现各种舍入算法,然后看看给出的结果与printf的真实%a相同。不应该那么难,因为不同的舍入算法只是在处理一半方面有所不同。其余的四舍五入到最接近的数字。
顺便说一句,我在您先前的问题(How %a conversion work in printf statement?)中说的是错误的:对于具有非舍入表示形式1.999999 .... p + 1和舍入表示形式1.99999ap + 1的3.2,最后一个“ a”将由于有限的浮点精度而发生。当然,它的发生是由于舍入而不是由于浮点精度的限制,正如您可能已经意识到的那样。