如何在%printf语句转换工作? [英] How %a conversion work in printf statement?
问题描述
也许这不属于对SO,但我不知道还有什么地方。
我不得不重新实现的printf(3)
与 C
不使用,会做这种转换我任何功能,我接近完成,但我被困在%A
,我真的不明白发生了什么位置,例如:
的printf(%A \\ N,3.0); //#=> 0x1.8p + 1
的printf(%A \\ N,3.1); //#=> 0x1.8cccccccccccdp + 1
的printf(%A \\ N,3.2); //#=> 0x1.999999999999ap + 1
的printf(%A \\ N,3.3); //#=> 0x1.a666666666666p + 1
的printf(%A \\ N,3.4); //#=> 0x1.b333333333333p + 1
的printf(%A \\ N,3.5); //#=> 0x1.cp + 1
的printf(%A \\ N,3.6); //#=> 0x1.ccccccccccccdp + 1
当然,我读到那个男子说:
双参数四舍五入并转换为十六进制
在款式[ - ] 0xh.hhhp [+ - ] d,其中数字后面的数字
十六进制点字符等于precision规范。
块引用>但是,这并不能真正帮助我不明白的过程的那个变换
3.2
到1.999999999999ap + 1
我不需要任何code,但实际上更多的解释。
PS:如果这不是地方这个问题,你可以点我到正确的位置。
编辑:在
@juhist
答案适用于数> =1.0
它没有解释如何获得导致对之间的数字0.0
等1.0
:的printf(%A \\ N,0.01); //#=> 0x1.47ae147ae147bp-7
的printf(%A \\ N,0.1); //#=> 0x1.999999999999ap-4
的printf(%A \\ N,0.2); //#=> 0x1.999999999999ap-3
的printf(%A \\ N,0.3); //#=> 0x1.3333333333333p-2
的printf(%A \\ N,0.4); //#=> 0x1.999999999999ap-2
的printf(%A \\ N,0.5); //#=> 0x1p-1
的printf(%A \\ N,0.6); //#=> 0x1.3333333333333p-1此外,我真的很喜欢在这样的precision
将A接近尾声的发生是由于有关转换
有限浮点计算precision:的printf(%A \\ N,3.2); //#=> 0x1.999999999999ap + 1
EDIT2:现在最后之谜是解释为什么在这种情况下:
的printf(%A \\ N,0.1); //#=> 0x1.999999999999ap-4
最后一个
9
变得和A
在这种情况下:的printf(%A \\ N,0.3); //#=> 0x1.3333333333333p-2
最后一个
3
保持一个3
?解决方案首先,你需要知道的再presentation
0xh.hhhh p±D,
意思?让我们通过采取十六进制常数的例子理解0x1.99999ap + 1
。结果
数字1
前的小数点是一个十六进制数字和数字
后其十六进制数字(99999a
)等于precision。0X
是十六进制引导和P
是指数字段。该指数是一个十进制数,表示通过该显著部分将倍增2
的力量。所以,当
0x1.99999ap + 1
将2
相乘1
那么这将十进制转换为3.2
。回想一下,如何1.55e + 1
十进制转换为15.500000
。类似的事情发生在这里。现在,你需要知道
0x1.99999ap + 1
的转换背后的数学3.2
。这将进行如下:
1 * 16 0 + 9 * 16 1 + 9 * 16 -2 + 9 * 16 -3 + 9 * 16 -4 + 9 * 16 -5 + 10 * 16 1
块引用>这是(十进制)等于
1.60000002384185791015625
您只需要到1 precision。因此,采取
1.6
和2
1 $ C $乘以C>
。这将给3.2
。要到你需要找到
2
的权重,据此浮点数将被划分到获得数字上面的过程1
之前小数点。后使用连续乘法来改变的小数部分为十六进制分数。步骤如下:
- 3.2 / 2 1 = 1.6
- 从1.6乘坐组成部分,以获得进制
1
小数点前。
- 乘
0.6
按16
。该整数部分获得的意志变成了十六进制部分的数字。重复此步骤与所获得的小数部分所需的precision(6默认值)。结果
- 0.6 * 16 = 9.6 --->积分部分= 9小数部分= 0.6
- 0.6 * 16 = 9.6 --->积分部分= 9小数部分= 0.6
- 0.6 * 16 = 9.6 --->积分部分= 9小数部分= 0.6
- 0.6 * 16 = 9.6 --->积分部分= 9小数部分= 0.6
- 0.6 * 16 = 9.6 --->积分部分= 9小数部分= 0.6
- 0.6 * 16 = 9.6 --->积分部分= 9小数部分= 0.6
块引用>
块引用>因此,十六进制分数将成为
0.999999
现在,小数点和指数字段一起获得得到的结果为十六进制部分结合之前六角指标0X
,十六进制数字。
3.2 <子> 10 = 0x1.999999p + 1 16
块引用>同样可以获取十六进制浮点数不到
数字1.0
,例如<0.01 / code>。在这种情况下取得两位数十六进制
1
之前,你需要将它与一个数字是2 $ C $的权力划分小数点C>。由于
128
(2 5 )与相乘后的<0.01 / code>将给予其组成部分的数量成为
1
,128 * 0.01 = 1.28
。这意味着你需要乘<0.01 / code> 1/2 -5 或者你可以说你需要除以2为 -5 获得
1.28
。现在应用步骤2和3如上所述。Maybe this doesn't belong on SO but I don't know where else.
I have to reimplement
printf(3)
withC
without using any function that would do the conversion for me, I'm nearly done, but I'm stuck on%a
, I really don't understand what is happening here for example:printf("%a\n", 3.0); //#=> 0x1.8p+1 printf("%a\n", 3.1); //#=> 0x1.8cccccccccccdp+1 printf("%a\n", 3.2); //#=> 0x1.999999999999ap+1 printf("%a\n", 3.3); //#=> 0x1.a666666666666p+1 printf("%a\n", 3.4); //#=> 0x1.b333333333333p+1 printf("%a\n", 3.5); //#=> 0x1.cp+1 printf("%a\n", 3.6); //#=> 0x1.ccccccccccccdp+1
Of course I read the man which says:
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.
But this doesn't really help I don't understand the process that transforms
3.2
to1.999999999999ap+1
I don't need any code but really more an explanation.
PS: If this isn't the place for this question could you point me to the right place?
EDIT: While
@juhist
answer works for numbers >=1.0
it doesn't explain how to get the result for numbers between0.0
et1.0
:printf("%a\n", 0.01); //#=> 0x1.47ae147ae147bp-7 printf("%a\n", 0.1); //#=> 0x1.999999999999ap-4 printf("%a\n", 0.2); //#=> 0x1.999999999999ap-3 printf("%a\n", 0.3); //#=> 0x1.3333333333333p-2 printf("%a\n", 0.4); //#=> 0x1.999999999999ap-2 printf("%a\n", 0.5); //#=> 0x1p-1 printf("%a\n", 0.6); //#=> 0x1.3333333333333p-1
Also I would really like a precision on this
The "a" near the end occurs due to limited floating point calculation precision
concerning the conversion:printf("%a\n", 3.2); //#=> 0x1.999999999999ap+1
EDIT2: Now the last mystery is to explain why in this case:
printf("%a\n", 0.1); //#=> 0x1.999999999999ap-4
The last
9
becomes anda
and in this case:printf("%a\n", 0.3); //#=> 0x1.3333333333333p-2
The last
3
stays a3
?解决方案First you need to know what the representation
0xh.hhhh p±d,
mean? Let's understand it by taking an example of hexadecimal constant0x1.99999ap+1
.
The digit1
before the decimal point is a hex digit and the number of hexadecimal digits after it (99999a
) is equal to the precision.0x
is the hex introducer and thep
is exponent field. The exponent is a decimal number that indicates the power of2
by which the significant part is multiplied.So, when
0x1.99999ap+1
will be multiplied with2
1
then it will be converted to3.2
in decimal. Recall that how1.55e+1
converted to15.500000
in decimal. Similar thing is happening here.Now you need to know the mathematics behind the conversion of
0x1.99999ap+1
to3.2
. This will proceed as follows1*160 + 9*16-1 + 9*16-2 + 9*16-3 + 9*16-4 + 9*16-5 + 10*16-1
Which is (in decimal) equal to
1.60000002384185791015625
You need only up to 1 precision. So, take
1.6
and multiply it with2
1
. Which will give3.2
.To go to the reverse of the above process you need to find power of
2
by which the floating point number will be divided to obtain the digit1
before decimal point. After that use successive multiplications to change the fractional part to hexadecimal fraction. Proceed as follows:
- 3.2/21 = 1.6
- Take integral part from 1.6 to obtain the hex-digit
1
before decimal point.- Multiply
.6
by16
. The the integral part obtained will becomes a numeral in the hexadecimal fraction. Repeat this step with the obtained fractional part to the desired precision (6 is default).
- .6 * 16 = 9.6 ---> Integral part = 9 Fractional part = .6
- .6 * 16 = 9.6 ---> Integral part = 9 Fractional part = .6
- .6 * 16 = 9.6 ---> Integral part = 9 Fractional part = .6
- .6 * 16 = 9.6 ---> Integral part = 9 Fractional part = .6
- .6 * 16 = 9.6 ---> Integral part = 9 Fractional part = .6
- .6 * 16 = 9.6 ---> Integral part = 9 Fractional part = .6
So the hexadecimal fraction will become
.999999
Now combine hex indicator0x
, hex-digit before decimal point and the hexadecimal fraction obtained along with exponent field to get the result.3.210 = 0x1.999999p+116
Similarly you can obtain hexadecimal floating point number for numbers less than
1.0
., for example0.01
. In this case to obtain the hex-digit1
before decimal point you need to divide it with a number which is power of2
. Since128
(25) after multiplying with0.01
will give the number whose integral part becomes1
,128*.01 = 1.28
. It means you need to multiply0.01
by 1/2-5 or you can say you need to divide it by 2-5 to get1.28
. Now apply the steps 2 and 3 stated above.这篇关于如何在%printf语句转换工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!