回答編集履歴

1

内容追記

2019/02/06 04:25

投稿

kazto
kazto

スコア7196

test CHANGED
@@ -16,6 +16,8 @@
16
16
 
17
17
  printf("%x\n", ul);
18
18
 
19
+ printf("%f\n", f);
20
+
19
21
  return 0;
20
22
 
21
23
  }
@@ -32,4 +34,114 @@
32
34
 
33
35
  3f333333
34
36
 
37
+ 0.700000
38
+
35
39
  ```
40
+
41
+
42
+
43
+ ---
44
+
45
+
46
+
47
+ ちょっと題意を読み違えました。。。
48
+
49
+
50
+
51
+ コンピュータにおいて、厳密に「0.7」という実数は存在し得ません。
52
+
53
+ 浮動小数点数は無限にある一方、コンピュータ内部では32bitとか64bitとか、情報量に制限があることが原因です。
54
+
55
+
56
+
57
+ そこでIEEEという組織が定めた浮動小数点数をコンピュータで表現するための仕様が、[IEEE754](https://ja.wikipedia.org/wiki/IEEE_754)になります。
58
+
59
+
60
+
61
+ その結果のコンピュータ内でのどう扱われているか、を示すのが先に示した「0x3f333333」という値になります。
62
+
63
+
64
+
65
+ ここまでは大丈夫でしょうか。
66
+
67
+
68
+
69
+ さて、浮動小数点数にはもう一つ問題があります。表示をどこまで表示するか、です。
70
+
71
+
72
+
73
+ C言語でターミナルに文字を表示する関数と言えば`printf`ですね。
74
+
75
+ 上記で述べたように、コンピュータ内で厳密に「0.7」という実数が存在できない以上、IEEE754に従ったデータ列を、仕様に従って表示する必要があります。
76
+
77
+
78
+
79
+ printfは一定の桁数までは表示してくれますが、これも限りがあります。
80
+
81
+ 0.7という実数は0.7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
82
+
83
+ と理論上イコールである必要がありますが、こんな長い数字を表現するには結構なデータ量が必要になります。
84
+
85
+
86
+
87
+ 一般的にprintfでは適当なところで切ってしまって、「ざっくり0.7」と表示しますが、以下のように桁数を増やしてやると、
88
+
89
+
90
+
91
+ ```C
92
+
93
+ #include <stdio.h>
94
+
95
+
96
+
97
+ int main(void)
98
+
99
+ {
100
+
101
+ float f = 0.7f;
102
+
103
+ unsigned int ul = *(unsigned int *)(&f);
104
+
105
+ double d = 0.7;
106
+
107
+ unsigned long long ull = *(unsigned long long *)(&d);
108
+
109
+
110
+
111
+ printf("%x\n", ul);
112
+
113
+ printf("%.25f\n", f);
114
+
115
+
116
+
117
+ printf("%llx\n", ull);
118
+
119
+ printf("%.25lf\n", d);
120
+
121
+ return 0;
122
+
123
+ }
124
+
125
+ ```
126
+
127
+
128
+
129
+ (ついでにdoubleも増やしてみました。)
130
+
131
+
132
+
133
+ ```Bash
134
+
135
+ $ gcc f.c && ./a.out
136
+
137
+ 3f333333
138
+
139
+ 0.6999999880790710449218750
140
+
141
+ 3fe6666666666666
142
+
143
+ 0.6999999999999999555910790
144
+
145
+ ```
146
+
147
+ 厳密な0.7からはズレていることが分かります。