只是作爲一種補充伊格納西奧巴斯克斯 - 艾布拉姆斯答案(這是 正確的答案),我寫了下面的程序來測試的 pow(2, i)
爲正整數精度i
:
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <inttypes.h>
int main(void)
{
printf(" i 2^i correct pow(2, i) error ulps\n");
printf("------------------------------------------------------------\n");
union { float f; uint32_t i; } x, y;
x.f = 1; // 2^i, correct value
float ulp_r = FLT_EPSILON; // ULP to the right of x
for (int i = 0; i < 128; i++, x.f *= 2, ulp_r *= 2) {
y.f = pow(2, i);
float error = y.f - x.f;
float ulp = error < 0 ? ulp_r/2 : ulp_r; // ULP(x - error)
printf("%3d %11.6g 0x%08"PRIx32" 0x%08"PRIx32" %12.6g %4g\n",
i, x.f, x.i, y.i, error, error/ulp);
}
return 0;
}
在我的電腦上(gcc 5.4.0/Ubuntu 16.04),這個程序報告零錯誤。 在Arduino Uno (avr-gcc 4.9.2/avr-libc 1.8.0)上運行相同的程序(通過正確的stdio設置),我得到的差錯大到 ULPs!下面是從歐諾輸出:
i 2^i correct pow(2, i) error ulps
------------------------------------------------------------
0 1 0x3f800000 0x3f800000 0 0
1 2 0x40000000 0x40000000 0 0
2 4 0x40800000 0x407ffffe -4.76837e-07 -2
3 8 0x41000000 0x40fffffc -1.90735e-06 -4
4 16 0x41800000 0x417ffffc -3.8147e-06 -4
5 32 0x42000000 0x41fffffa -1.14441e-05 -6
6 64 0x42800000 0x427ffffa -2.28882e-05 -6
7 128 0x43000000 0x42fffffa -4.57764e-05 -6
8 256 0x43800000 0x437ffffa -9.15527e-05 -6
9 512 0x44000000 0x43fffff4 -0.000366211 -12
10 1024 0x44800000 0x447ffff4 -0.000732422 -12
11 2048 0x45000000 0x44fffff4 -0.00146484 -12
12 4096 0x45800000 0x457ffff4 -0.00292969 -12
13 8192 0x46000000 0x46000000 0 0
14 16384 0x46800000 0x467ffff4 -0.0117188 -12
15 32768 0x47000000 0x46fffff4 -0.0234375 -12
16 65536 0x47800000 0x477ffff4 -0.046875 -12
17 131072 0x48000000 0x48000000 0 0
18 262144 0x48800000 0x487fffea -0.34375 -22
19 524288 0x49000000 0x48ffffea -0.6875 -22
20 1.04858e+06 0x49800000 0x497fffea -1.375 -22
21 2.09715e+06 0x4a000000 0x4a000000 0 0
22 4.1943e+06 0x4a800000 0x4a7fffea -5.5 -22
23 8.38861e+06 0x4b000000 0x4affffea -11 -22
24 1.67772e+07 0x4b800000 0x4b7fffea -22 -22
25 3.35544e+07 0x4c000000 0x4c000000 0 0
26 6.71089e+07 0x4c800000 0x4c800000 0 0
27 1.34218e+08 0x4d000000 0x4cffffea -176 -22
28 2.68435e+08 0x4d800000 0x4d7fffea -352 -22
29 5.36871e+08 0x4e000000 0x4e000000 0 0
30 1.07374e+09 0x4e800000 0x4e7fffea -1408 -22
31 2.14748e+09 0x4f000000 0x4effffea -2816 -22
32 4.29497e+09 0x4f800000 0x4f7fffea -5632 -22
33 8.58993e+09 0x50000000 0x50000000 0 0
34 1.71799e+10 0x50800000 0x50800000 0 0
35 3.43597e+10 0x51000000 0x50ffffd2 -94208 -46
36 6.87195e+10 0x51800000 0x517fffd2 -188416 -46
37 1.37439e+11 0x52000000 0x52000000 0 0
38 2.74878e+11 0x52800000 0x527fffd2 -753664 -46
39 5.49756e+11 0x53000000 0x52ffffd2 -1.50733e+06 -46
40 1.09951e+12 0x53800000 0x537fffd2 -3.01466e+06 -46
41 2.19902e+12 0x54000000 0x54000000 0 0
42 4.39805e+12 0x54800000 0x54800000 0 0
43 8.79609e+12 0x55000000 0x54ffffd2 -2.41172e+07 -46
44 1.75922e+13 0x55800000 0x557fffd2 -4.82345e+07 -46
45 3.51844e+13 0x56000000 0x56000000 0 0
46 7.03687e+13 0x56800000 0x567fffd2 -1.92938e+08 -46
47 1.40737e+14 0x57000000 0x57000000 0 0
48 2.81475e+14 0x57800000 0x577fffd2 -7.71752e+08 -46
49 5.6295e+14 0x58000000 0x57ffffd2 -1.5435e+09 -46
50 1.1259e+15 0x58800000 0x58800000 0 0
51 2.2518e+15 0x59000000 0x58ffffd2 -6.17402e+09 -46
52 4.5036e+15 0x59800000 0x59800000 0 0
53 9.0072e+15 0x5a000000 0x5a000000 0 0
54 1.80144e+16 0x5a800000 0x5a7fffd2 -4.93921e+10 -46
55 3.60288e+16 0x5b000000 0x5b000000 0 0
56 7.20576e+16 0x5b800000 0x5b7fffd2 -1.97568e+11 -46
57 1.44115e+17 0x5c000000 0x5bffffd2 -3.95137e+11 -46
58 2.8823e+17 0x5c800000 0x5c800000 0 0
59 5.76461e+17 0x5d000000 0x5cffffd2 -1.58055e+12 -46
60 1.15292e+18 0x5d800000 0x5d7fffd2 -3.1611e+12 -46
61 2.30584e+18 0x5e000000 0x5e000000 0 0
62 4.61169e+18 0x5e800000 0x5e7fffd2 -1.26444e+13 -46
63 9.22337e+18 0x5f000000 0x5f000000 0 0
64 1.84467e+19 0x5f800000 0x5f7fffd2 -5.05775e+13 -46
65 3.68935e+19 0x60000000 0x5fffffa6 -1.97912e+14 -90
66 7.3787e+19 0x60800000 0x60800000 0 0
67 1.47574e+20 0x61000000 0x60ffffa6 -7.91648e+14 -90
68 2.95148e+20 0x61800000 0x61800000 0 0
69 5.90296e+20 0x62000000 0x61ffffa6 -3.16659e+15 -90
70 1.18059e+21 0x62800000 0x627fffa6 -6.33319e+15 -90
71 2.36118e+21 0x63000000 0x63000000 0 0
72 4.72237e+21 0x63800000 0x637fffa6 -2.53327e+16 -90
73 9.44473e+21 0x64000000 0x63ffffa6 -5.06655e+16 -90
74 1.88895e+22 0x64800000 0x64800000 0 0
75 3.77789e+22 0x65000000 0x64ffffa6 -2.02662e+17 -90
76 7.55579e+22 0x65800000 0x657fffa6 -4.05324e+17 -90
77 1.51116e+23 0x66000000 0x65ffffa6 -8.10648e+17 -90
78 3.02231e+23 0x66800000 0x667fffa6 -1.6213e+18 -90
79 6.04463e+23 0x67000000 0x67000000 0 0
80 1.20893e+24 0x67800000 0x677fffa6 -6.48518e+18 -90
81 2.41785e+24 0x68000000 0x67ffffa6 -1.29704e+19 -90
82 4.8357e+24 0x68800000 0x68800000 0 0
83 9.67141e+24 0x69000000 0x68ffffa6 -5.18815e+19 -90
84 1.93428e+25 0x69800000 0x69800000 0 0
85 3.86856e+25 0x6a000000 0x69ffffa6 -2.07526e+20 -90
86 7.73713e+25 0x6a800000 0x6a7fffa6 -4.15052e+20 -90
87 1.54743e+26 0x6b000000 0x6b000000 0 0
88 3.09485e+26 0x6b800000 0x6b7fffa6 -1.66021e+21 -90
89 6.1897e+26 0x6c000000 0x6bffffa6 -3.32041e+21 -90
90 1.23794e+27 0x6c800000 0x6c800000 0 0
91 2.47588e+27 0x6d000000 0x6cffffa6 -1.32817e+22 -90
92 4.95176e+27 0x6d800000 0x6d7fffa6 -2.65633e+22 -90
93 9.90352e+27 0x6e000000 0x6dffffa6 -5.31266e+22 -90
94 1.9807e+28 0x6e800000 0x6e800000 0 0
95 3.96141e+28 0x6f000000 0x6f000000 0 0
96 7.92282e+28 0x6f800000 0x6f7fffa6 -4.25013e+23 -90
97 1.58456e+29 0x70000000 0x6fffffa6 -8.50026e+23 -90
98 3.16913e+29 0x70800000 0x707fffa6 -1.70005e+24 -90
99 6.33825e+29 0x71000000 0x71000000 0 0
100 1.26765e+30 0x71800000 0x71800000 0 0
101 2.5353e+30 0x72000000 0x71ffffa6 -1.36004e+25 -90
102 5.0706e+30 0x72800000 0x727fffa6 -2.72008e+25 -90
103 1.01412e+31 0x73000000 0x72ffffa6 -5.44017e+25 -90
104 2.02824e+31 0x73800000 0x73800000 0 0
105 4.05648e+31 0x74000000 0x74000000 0 0
106 8.11296e+31 0x74800000 0x74800000 0 0
107 1.62259e+32 0x75000000 0x74ffffa6 -8.70427e+26 -90
108 3.24519e+32 0x75800000 0x757fffa6 -1.74085e+27 -90
109 6.49037e+32 0x76000000 0x75ffffa6 -3.48171e+27 -90
110 1.29807e+33 0x76800000 0x76800000 0 0
111 2.59615e+33 0x77000000 0x77000000 0 0
112 5.1923e+33 0x77800000 0x777fffa6 -2.78537e+28 -90
113 1.03846e+34 0x78000000 0x77ffffa6 -5.57073e+28 -90
114 2.07692e+34 0x78800000 0x787fffa6 -1.11415e+29 -90
115 4.15384e+34 0x79000000 0x79000000 0 0
116 8.30767e+34 0x79800000 0x79800000 0 0
117 1.66153e+35 0x7a000000 0x79ffffa6 -8.91317e+29 -90
118 3.32307e+35 0x7a800000 0x7a7fffa6 -1.78263e+30 -90
119 6.64614e+35 0x7b000000 0x7affffa6 -3.56527e+30 -90
120 1.32923e+36 0x7b800000 0x7b7fffa6 -7.13053e+30 -90
121 2.65846e+36 0x7c000000 0x7c000000 0 0
122 5.31691e+36 0x7c800000 0x7c800000 0 0
123 1.06338e+37 0x7d000000 0x7cffffa6 -5.70443e+31 -90
124 2.12676e+37 0x7d800000 0x7d7fffa6 -1.14089e+32 -90
125 4.25353e+37 0x7e000000 0x7dffffa6 -2.28177e+32 -90
126 8.50706e+37 0x7e800000 0x7e800000 0 0
127 1.70141e+38 0x7f000000 0x7f000000 0 0
有幾點值得注意:
- 和
FLT_MAX
兩者之間FLT_MIN
每次開機正是 表示爲一個float
- 的IEEE-754標準需要操作+, - ,×,÷和√是 正確的舍入,這意味着2 通過 計算我迭代multiplyin通過2克保證得到精確的結果
- 同一標準並不要求
pow
被正確地舍入。
您的意思是使用'1 << N'? –
不確定你的意思。我的意思是使用大的n值嗎? No. –
我的意思是'(int)pow(2,n)'是不應該寫的東西。 'pow'是用於浮點的。 C++有'運營商<<',其中'1 << N'給出了2 –