-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path09_add_sub_unbias_round.html
607 lines (574 loc) · 48.8 KB
/
09_add_sub_unbias_round.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>9 加减法和无偏差舍入的迷 — THE END of ERROR - Unum Computing 0.1 documentation</title>
<link rel="stylesheet" href="_static/material-design-lite-1.3.0/material.blue-deep_orange.min.css" type="text/css" />
<link rel="stylesheet" href="_static/sphinx_materialdesign_theme.css" type="text/css" />
<link rel="stylesheet" href="_static/fontawesome/all.css" type="text/css" />
<link rel="stylesheet" href="_static/fonts.css" type="text/css" />
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/basic.css" />
<link rel="stylesheet" type="text/css" href="_static/d2l.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<script src="_static/d2l.js"></script>
<script async="async" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="10 乘法和除法" href="10_mul_div.html" />
<link rel="prev" title="8 比较操作" href="08_comparison_operations.html" />
</head>
<body>
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header mdl-layout--fixed-drawer"><header class="mdl-layout__header mdl-layout__header--waterfall ">
<div class="mdl-layout__header-row">
<nav class="mdl-navigation breadcrumb">
<a class="mdl-navigation__link is-active">9 加减法和无偏差舍入的迷</a>
</nav>
<div class="mdl-layout-spacer"></div>
<nav class="mdl-navigation">
<form class="form-inline pull-sm-right" action="search.html" method="get">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield--floating-label mdl-textfield--align-right">
<label id="quick-search-icon" class="mdl-button mdl-js-button mdl-button--icon" for="waterfall-exp">
<i class="material-icons">search</i>
</label>
<div class="mdl-textfield__expandable-holder">
<input class="mdl-textfield__input" type="text" name="q" id="waterfall-exp" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</div>
</div>
<div class="mdl-tooltip" data-mdl-for="quick-search-icon">
Quick search
</div>
</form>
<a id="button-show-source"
class="mdl-button mdl-js-button mdl-button--icon"
href="_sources/09_add_sub_unbias_round.rst.txt" rel="nofollow">
<i class="material-icons">code</i>
</a>
<div class="mdl-tooltip" data-mdl-for="button-show-source">
Show Source
</div>
</nav>
</div>
<div class="mdl-layout__header-row header-links">
<div class="mdl-layout-spacer"></div>
<nav class="mdl-navigation">
<a class="mdl-navigation__link" href="https://github.com/jszheng/TheEndOfError">
<i class="fab fa-github"></i>
Github
</a>
</nav>
</div>
</header><header class="mdl-layout__drawer">
<!-- Title -->
<span class="mdl-layout-title">
<a class="title" href="index.html">
<span class="title-text">
THE END of ERROR - Unum Computing
</span>
</a>
</span>
<div class="globaltoc">
<span class="mdl-layout-title toc">Table Of Contents</span>
<nav class="mdl-navigation">
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Preface.html">Preface</a></li>
<li class="toctree-l1"><a class="reference internal" href="00_how_to_read.html">如何读这本书</a></li>
<li class="toctree-l1"><a class="reference internal" href="Part1.html">Part 1 一种新的数字格式Unum</a></li>
<li class="toctree-l1"><a class="reference internal" href="01_Overview.html">1 概论</a></li>
<li class="toctree-l1"><a class="reference internal" href="02_BuildUpUnumFormat.html">2. 构造unum的格式</a></li>
<li class="toctree-l1"><a class="reference internal" href="03_TheOriginalSin.html">3. 计算机算术的原罪</a></li>
<li class="toctree-l1"><a class="reference internal" href="04_unum_format.html">4. 完整的unum格式定义</a></li>
<li class="toctree-l1"><a class="reference internal" href="05_hidden_scratchpads_3_layers.html">5. 隐藏的草稿本和三个层次</a></li>
<li class="toctree-l1"><a class="reference internal" href="06_info_per_bit.html">6 每个比特的信息</a></li>
<li class="toctree-l1"><a class="reference internal" href="07_fixed_size_unum_storage.html">7 定长的unum存储</a></li>
<li class="toctree-l1"><a class="reference internal" href="08_comparison_operations.html">8 比较操作</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">9 加减法和无偏差舍入的迷</a></li>
<li class="toctree-l1"><a class="reference internal" href="10_mul_div.html">10 乘法和除法</a></li>
<li class="toctree-l1"><a class="reference internal" href="11_power.html">11 求幂</a></li>
<li class="toctree-l1"><a class="reference internal" href="12_other_important_unary_ops.html">12 其他重要的一元运算</a></li>
<li class="toctree-l1"><a class="reference internal" href="13_fused_operations.html">13 融合操作(一次性表达式)</a></li>
<li class="toctree-l1"><a class="reference internal" href="14_trial_runs.html">14 试运行:Unums 面临计算挑战</a></li>
<li class="toctree-l1"><a class="reference internal" href="part1_summary.html">小结</a></li>
<li class="toctree-l1"><a class="reference internal" href="Part2.html">Part 2 - 一种新的解决方法 Ubox</a></li>
<li class="toctree-l1"><a class="reference internal" href="15_TheOtherKindOfError.html">15. 另外一种误差</a></li>
<li class="toctree-l1"><a class="reference internal" href="16_avoid_interval_arith_pitfalls.html">16 避免区间算术陷阱</a></li>
<li class="toctree-l1"><a class="reference internal" href="17_meaning_of_solve_equ.html">17 “解”方程到底是什么意思?</a></li>
<li class="toctree-l1"><a class="reference internal" href="18_permission_to_guess.html">18 准许猜测</a></li>
<li class="toctree-l1"><a class="reference internal" href="19_pendulums_done_correctly.html">19 摆的正确计算</a></li>
<li class="toctree-l1"><a class="reference internal" href="20_two_body_problem.html">20 二体问题(以及多体问题)</a></li>
<li class="toctree-l1"><a class="reference internal" href="21_calculus_evil.html">21 微积分被认为是邪恶的:离散物理</a></li>
<li class="toctree-l1"><a class="reference internal" href="22_end_of_error.html">22 错误的终结</a></li>
<li class="toctree-l1"><a class="reference internal" href="Glossary.html">词汇表</a></li>
</ul>
</nav>
</div>
</header>
<main class="mdl-layout__content" tabIndex="0">
<script type="text/javascript" src="_static/sphinx_materialdesign_theme.js "></script>
<header class="mdl-layout__drawer">
<!-- Title -->
<span class="mdl-layout-title">
<a class="title" href="index.html">
<span class="title-text">
THE END of ERROR - Unum Computing
</span>
</a>
</span>
<div class="globaltoc">
<span class="mdl-layout-title toc">Table Of Contents</span>
<nav class="mdl-navigation">
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Preface.html">Preface</a></li>
<li class="toctree-l1"><a class="reference internal" href="00_how_to_read.html">如何读这本书</a></li>
<li class="toctree-l1"><a class="reference internal" href="Part1.html">Part 1 一种新的数字格式Unum</a></li>
<li class="toctree-l1"><a class="reference internal" href="01_Overview.html">1 概论</a></li>
<li class="toctree-l1"><a class="reference internal" href="02_BuildUpUnumFormat.html">2. 构造unum的格式</a></li>
<li class="toctree-l1"><a class="reference internal" href="03_TheOriginalSin.html">3. 计算机算术的原罪</a></li>
<li class="toctree-l1"><a class="reference internal" href="04_unum_format.html">4. 完整的unum格式定义</a></li>
<li class="toctree-l1"><a class="reference internal" href="05_hidden_scratchpads_3_layers.html">5. 隐藏的草稿本和三个层次</a></li>
<li class="toctree-l1"><a class="reference internal" href="06_info_per_bit.html">6 每个比特的信息</a></li>
<li class="toctree-l1"><a class="reference internal" href="07_fixed_size_unum_storage.html">7 定长的unum存储</a></li>
<li class="toctree-l1"><a class="reference internal" href="08_comparison_operations.html">8 比较操作</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">9 加减法和无偏差舍入的迷</a></li>
<li class="toctree-l1"><a class="reference internal" href="10_mul_div.html">10 乘法和除法</a></li>
<li class="toctree-l1"><a class="reference internal" href="11_power.html">11 求幂</a></li>
<li class="toctree-l1"><a class="reference internal" href="12_other_important_unary_ops.html">12 其他重要的一元运算</a></li>
<li class="toctree-l1"><a class="reference internal" href="13_fused_operations.html">13 融合操作(一次性表达式)</a></li>
<li class="toctree-l1"><a class="reference internal" href="14_trial_runs.html">14 试运行:Unums 面临计算挑战</a></li>
<li class="toctree-l1"><a class="reference internal" href="part1_summary.html">小结</a></li>
<li class="toctree-l1"><a class="reference internal" href="Part2.html">Part 2 - 一种新的解决方法 Ubox</a></li>
<li class="toctree-l1"><a class="reference internal" href="15_TheOtherKindOfError.html">15. 另外一种误差</a></li>
<li class="toctree-l1"><a class="reference internal" href="16_avoid_interval_arith_pitfalls.html">16 避免区间算术陷阱</a></li>
<li class="toctree-l1"><a class="reference internal" href="17_meaning_of_solve_equ.html">17 “解”方程到底是什么意思?</a></li>
<li class="toctree-l1"><a class="reference internal" href="18_permission_to_guess.html">18 准许猜测</a></li>
<li class="toctree-l1"><a class="reference internal" href="19_pendulums_done_correctly.html">19 摆的正确计算</a></li>
<li class="toctree-l1"><a class="reference internal" href="20_two_body_problem.html">20 二体问题(以及多体问题)</a></li>
<li class="toctree-l1"><a class="reference internal" href="21_calculus_evil.html">21 微积分被认为是邪恶的:离散物理</a></li>
<li class="toctree-l1"><a class="reference internal" href="22_end_of_error.html">22 错误的终结</a></li>
<li class="toctree-l1"><a class="reference internal" href="Glossary.html">词汇表</a></li>
</ul>
</nav>
</div>
</header>
<div class="document">
<div class="page-content" role="main">
<div class="section" id="id1">
<h1>9 加减法和无偏差舍入的迷<a class="headerlink" href="#id1" title="Permalink to this heading">¶</a></h1>
<div class="figure align-default" id="id5">
<img alt="_images/image-20230620123711433.png" src="_images/image-20230620123711433.png" />
<p class="caption"><span class="caption-number">Fig. 117 </span><span class="caption-text">image-20230620123711433</span><a class="headerlink" href="#id5" title="Permalink to this image">¶</a></p>
</div>
<blockquote>
<div><p>1982 年,温哥华证券交易所建立了股票指数,初始值设为
1000。尽管经济健康,但该指数在接下来的两年内稳步下降至 520。
该指数是通过加减股票变化来更新的,使用舍入到小数点后三位十进制的浮点数,因此舍入误差会累积。
如果根据实际股价重新计算股票指数,显示该指数实际上是 1098,而不是
520。如果使用 unum 算法,近似值的累积会很明显被发现的。</p>
</div></blockquote>
<div class="section" id="id2">
<h2>9.1 重新学习加法表…对实数<a class="headerlink" href="#id2" title="Permalink to this heading">¶</a></h2>
<p>原型使用“<span class="math notranslate nohighlight">\(\oplus\)</span>”来代表ubound和unum的加法,所以计算“-3+7.5”用ubound就被记为“<span class="math notranslate nohighlight">\(\hat{-3}\oplus\hat{7.5}\)</span>”。这有点像是bizarro
arithmetic,每一个数和每一个操作都被稍微改动了,提醒我们这是计算机的操作,跟纯粹数学的操作不一样的。</p>
<p>现在我们开始对unum和ubound做一些基本的算术,然后追踪用了多少bit并跟用IEEE浮点数做来比较使用的比特数。每个unum的比特数不同,所以原型中定了ubitsmoved和numbersmoved两个全局变量,可以在运行计算例程前清零。最简单的比较代价的方式是看ubitsmoved/numbermoved的比例,这告诉我们平均每个数消耗的比特数目。一个加法从存储中读入两个数,写出一个答案。所以加3到numbersmoved。而ubitsmoved计数器则加上所有输入输出的ubound比特数目(通过nbits函数得到)。</p>
<p>在一个真正的硬件系统中我们也许不太需要考虑测量数据搬移代价,但是我们需要实验数据回答以下问题</p>
<blockquote>
<div><p>在完整解决一个实际问题时候,unum比起float更省空间吗?</p>
</div></blockquote>
<p>传统间隔算术做加法是很直接的。[a, b]和[c, d]相加结果是[a+c,
b+d]。a+b向<span class="math notranslate nohighlight">\(-\infty\)</span>舍入,而b+d向<span class="math notranslate nohighlight">\(+\infty\)</span>舍入。但是ubound更复杂些,需要处理端点开/闭,动态指数小数长度,和结果超出最大可表示数maxreal等问题。比如<span class="math notranslate nohighlight">\((-\infty, 0)\)</span>加上<span class="math notranslate nohighlight">\(\infty\)</span>,正确的答案是<span class="math notranslate nohighlight">\(\infty\)</span>.
因为开的端点<span class="math notranslate nohighlight">\(-\infty\)</span>表示的是实际上有限的一个数,加上<span class="math notranslate nohighlight">\(\infty\)</span>总是<span class="math notranslate nohighlight">\(\infty\)</span>。</p>
<p>ubound加法需要两张表,一张对左端点,使用“[x”或“(x”表示,一张对右端点,
使用“x]”或“x)”表示。大括号用在一些非常奇怪的表示上。</p>
<p>这包括了所有可能。每个实现unum计算的人都需要深思一下表中的一些情况,例如</p>
<ul class="simple">
<li><p>“<span class="math notranslate nohighlight">\((-\infty \oplus [\infty = [\infty\)</span>” 和
“<span class="math notranslate nohighlight">\(-\infty] \oplus \infty )= -\infty]\)</span>” :
包含的无穷赢过不包含的无穷</p></li>
<li><p>“<span class="math notranslate nohighlight">\(( \infty\)</span>” 和
“<span class="math notranslate nohighlight">\(-\infty)\)</span>”不存在,不包含在表中。注意这是开区间情况,闭区间可以有<span class="math notranslate nohighlight">\([\infty\)</span>,
当然一定配<span class="math notranslate nohighlight">\(\infty]\)</span>,同样的也可以有<span class="math notranslate nohighlight">\([-\infty, -\infty]\)</span></p></li>
<li><p>如果“<span class="math notranslate nohighlight">\([x \oplus [y\)</span>”结果超出了maxreal,
那么结果是“<span class="math notranslate nohighlight">\((maxreal\)</span>” 而不是“<span class="math notranslate nohighlight">\([maxreal\)</span>”</p></li>
<li><p>如果“<span class="math notranslate nohighlight">\(x] \oplus y]\)</span>”结果超出了maxreal,
那么结果是“<span class="math notranslate nohighlight">\(\infty)\)</span>”</p></li>
<li><p>类似的规则对-maxreal</p></li>
<li><p>即使是精确数的闭区间端点,在g-layer做了计算后,转换回u-layer的时候还是有可能变成不精确的开区间端点。只要结果落在u-layer的一个ulp的区间。(前面maxreal其实就是一个例子)</p></li>
</ul>
<p>IEEE标准不能很好地处理这些微妙的无穷的情况,而只是简单地产生一个NaN的结果。由于溢出在IEEE标准中变成了无穷,float实际上在结果中引入了无穷大的误差。unum纠正了这个错误,能表示一个数过于大以至于不能表示,但是是有限的。唯一产生NaN的情况是精确的<span class="math notranslate nohighlight">\(–\infty\)</span>加精确的<span class="math notranslate nohighlight">\(+\infty\)</span>,这个是无解的终极拉锯战。</p>
<p>下面是表了,罩住了整个实数线和无穷。x,
y是精确可表示的u-layer数,如果结果是加法的和,用黑色。异常则使用洋红色。同样的端点的开闭是or上两个inexact标记。</p>
<p>首先是g-layer加左端点的表</p>
<div class="figure align-default" id="id6">
<img alt="_images/image-20230620140839266.png" src="_images/image-20230620140839266.png" />
<p class="caption"><span class="caption-number">Fig. 118 </span><span class="caption-text">image-20230620140839266</span><a class="headerlink" href="#id6" title="Permalink to this image">¶</a></p>
</div>
<p>其次是g-layer加右端点的表</p>
<div class="figure align-default" id="id7">
<img alt="_images/image-20230620140903172.png" src="_images/image-20230620140903172.png" />
<p class="caption"><span class="caption-number">Fig. 119 </span><span class="caption-text">image-20230620140903172</span><a class="headerlink" href="#id7" title="Permalink to this image">¶</a></p>
</div>
<p>解包的unum格式比较容易看出在表中的位置。比如
“<span class="math notranslate nohighlight">\(-\infty]\)</span>”就是<span class="math notranslate nohighlight">\(b_{63}\)</span>(小于0) 与上
<span class="math notranslate nohighlight">\(b_{61}\)</span>(无穷) 与上 非<span class="math notranslate nohighlight">\(b_9\)</span> (不精确)</p>
<p>返回到u-layer是很简单,除了要主要那些包含有[x+y 和
x+y]的情况。如果x+y的几个不是个可表示的精确值,那么需要换为包含它的非精确值,从而改变为开区间。这包含当x+y小于-maxreal或是大于maxreal是,端点就变成区间<span class="math notranslate nohighlight">\((-\infty, -maxreal)\)</span>和<span class="math notranslate nohighlight">\((maxreal, \infty)\)</span>.附录C.9有加法的代码,也是根据上面的表,gbound处理然后转回ubound.
还自动检查unify是否可以做到无损压缩,如果可以就返回压缩的模式。</p>
<p>原型用函数negateu来将一个ubound去负数。ubound的减法<span class="math notranslate nohighlight">\(\ominus\)</span>就是把减法换成加负值。就是在g-layer中做<span class="math notranslate nohighlight">\(x-y=x+(-y)\)</span>,最后再讲结果转回会u-layer。</p>
<div class="section" id="id3">
<h3>9.1.1 例子和测试数据搬移量<a class="headerlink" href="#id3" title="Permalink to this heading">¶</a></h3>
<p>尝试一个含无穷的例子,有开和闭区间。为了清晰,我们把输入表示为间隔,再转换成ubound来计算。所以<span class="math notranslate nohighlight">\((-\infty, 4) \oplus (maxreal, \infty]\)</span>的结果是<span class="math notranslate nohighlight">\((-\infty, \infty]\)</span></p>
<div class="figure align-default" id="id8">
<img alt="_images/image-20230620151118566.png" src="_images/image-20230620151118566.png" />
<p class="caption"><span class="caption-number">Fig. 120 </span><span class="caption-text">image-20230620151118566</span><a class="headerlink" href="#id8" title="Permalink to this image">¶</a></p>
</div>
<p>左边变为开区间</p>
<div class="figure align-default" id="id9">
<img alt="_images/image-20230620151241275.png" src="_images/image-20230620151241275.png" />
<p class="caption"><span class="caption-number">Fig. 121 </span><span class="caption-text">image-20230620151241275</span><a class="headerlink" href="#id9" title="Permalink to this image">¶</a></p>
</div>
<p>无穷减无穷是NaN</p>
<div class="figure align-default" id="id10">
<img alt="_images/image-20230620151427862.png" src="_images/image-20230620151427862.png" />
<p class="caption"><span class="caption-number">Fig. 122 </span><span class="caption-text">image-20230620151427862</span><a class="headerlink" href="#id10" title="Permalink to this image">¶</a></p>
</div>
<p>尝试在一个{3,4}环境中做(2.25,
2.5)加9,并且记录数据搬移量。加ubitmask是表示2.25右边一个ULP的区间,长度0.25.
在u-layer, 这些数的表示如下</p>
<div class="figure align-default" id="id11">
<img alt="_images/image-20230620151810117.png" src="_images/image-20230620151810117.png" />
<p class="caption"><span class="caption-number">Fig. 123 </span><span class="caption-text">image-20230620151810117</span><a class="headerlink" href="#id11" title="Permalink to this image">¶</a></p>
</div>
<p>两个unum分别占用了13和15bit,我们还需要一比特记录是否是一部分还是两部分的ubound。ubound占用14和16bit。重置计数器,看结果</p>
<div class="figure align-default" id="id12">
<img alt="_images/image-20230620152202909.png" src="_images/image-20230620152202909.png" />
<p class="caption"><span class="caption-number">Fig. 124 </span><span class="caption-text">image-20230620152202909</span><a class="headerlink" href="#id12" title="Permalink to this image">¶</a></p>
</div>
<p>结果自动被扩展为18bit
ubound。使用原型定义的函数汇报数据搬移量,得到如下表报告</p>
<div class="figure align-default" id="id13">
<img alt="_images/image-20230620152426725.png" src="_images/image-20230620152426725.png" />
<p class="caption"><span class="caption-number">Fig. 125 </span><span class="caption-text">image-20230620152426725</span><a class="headerlink" href="#id13" title="Permalink to this image">¶</a></p>
</div>
<p>相同符合两个数相加通常会增加小数位数,或是指数位(未必,因为和的小数有可能reduce
to lower
term?)。特别是对于指数相差过大的数,比如我们用手工做做<span class="math notranslate nohighlight">\(2.0\times 10^{14}\)</span>和17的加法,
想得到的结果是精确的,你就需要写下所有的数字: 200000000000017</p>
<p>减法,或者加两个符合不同的数,有可能导致小数消除左边有效位,这就减少了需要的指数位数。所以减法有时候得到结果的更短。</p>
</div>
<div class="section" id="ubound">
<h3>9.1.2 三维可视化ubound的加法<a class="headerlink" href="#ubound" title="Permalink to this heading">¶</a></h3>
<p>还记得我们把一个通常的间隔用实数线上的粗的线段来表示,圆的边角代表开区间,方的代表闭区间。现在我们有两个间隔了,用同样的方式来表示为一个二维的块。例如下图是代表x是[-1,
5), y是(-2, 4]:</p>
<div class="figure align-default" id="id14">
<img alt="_images/image-20230620154932159.png" src="_images/image-20230620154932159.png" />
<p class="caption"><span class="caption-number">Fig. 126 </span><span class="caption-text">image-20230620154932159</span><a class="headerlink" href="#id14" title="Permalink to this image">¶</a></p>
</div>
<p>注意边角代表了开闭空间,只有一个角是完全方的,就是backview中(x=-1,
y=4的位置),其他都都是圆角。加法的结果表示为一个平面但最终投影在实线上,两边都是开区间。</p>
<div class="figure align-default" id="id15">
<img alt="_images/image-20230620155456424.png" src="_images/image-20230620155456424.png" />
<p class="caption"><span class="caption-number">Fig. 127 </span><span class="caption-text">image-20230620155456424</span><a class="headerlink" href="#id15" title="Permalink to this image">¶</a></p>
</div>
</div>
<div class="section" id="unum">
<h3>9.1.3 unum加减法的硬件实现<a class="headerlink" href="#unum" title="Permalink to this heading">¶</a></h3>
<p>unum
端点的加法和减法非常类似于传统浮点数的加法和减法,已经有很多文献都写过了。
这两种情况下一旦处理了异常,确定了隐藏位,就可以排列二进制小数点,然后像做十进制加法样一样从右到左按位做二进制加法。
由于使用不精确的 unums 或 ubounds
将需要两个端点对,因此设计一对可以并行执行的加/减单元是有意义的。</p>
<p>还有个重要的不同是关于舍入的。当结果的小数超出了可以容纳的量,
IEEE的浮点要求一个复杂的硬件选择一个不正确的浮点值来代表答案,有4种可以选择的舍入模式。而unum就简单地设置好ubit表明在最后一个比特后面还有更多的比特作为答案。这个做法和解包unum格式的预译码的异常位和隐藏位,表明unum的每一个端点的加减执行都会快些且花费更少的功耗。这有利与补偿使用两个部分的ubound需要做两次加减法。</p>
<p>假设一个浮点数有 p 个小数位。 每当指数相差超过 p
时,它表示当二进制小数点排列时分数之间不会重叠,因此逻辑可以采取捷径来计算如何舍入数字。
unum对于同样的数可能存储少于 p 位,但也有支持大于 p 的最大
fsize,可以在大部分时间捕获正确答案。</p>
<p>比如这是在{3,4}环境中的两个unum</p>
<div class="figure align-default" id="id16">
<img alt="_images/image-20230620161742352.png" src="_images/image-20230620161742352.png" />
<p class="caption"><span class="caption-number">Fig. 128 </span><span class="caption-text">image-20230620161742352</span><a class="headerlink" href="#id16" title="Permalink to this image">¶</a></p>
</div>
<p>指数相差12 (<span class="math notranslate nohighlight">\(2^{-8}对\)</span> <span class="math notranslate nohighlight">\(2^4\)</span>)。如果是两个IEEE
16比特浮点相加,硬件检测到指数差已经超过小数10比特的长度,那么就直接丢弃掉小的数,回答是<span class="math notranslate nohighlight">\(30+\frac{1}{256}=30\)</span>
。unum硬件检测到指数的差异跟最大的小数长度<span class="math notranslate nohighlight">\(2^{fsizesize}=16\)</span>,
就直接提升精度来完成这个加法</p>
<div class="figure align-default" id="id17">
<img alt="_images/image-20230620162524967.png" src="_images/image-20230620162524967.png" />
<p class="caption"><span class="caption-number">Fig. 129 </span><span class="caption-text">image-20230620162524967</span><a class="headerlink" href="#id17" title="Permalink to this image">¶</a></p>
</div>
<p>如果我们检测到指数差异超过了<span class="math notranslate nohighlight">\(2^{fsizesize}\)</span>,就可以采用捷径,直接标注数据是不精确的。比如<span class="math notranslate nohighlight">\(\hat{1000}\oplus\hat{\frac{1}{256}}\)</span>
就可以快速地给出一个正确的不精确结果</p>
<div class="figure align-default" id="id18">
<img alt="_images/image-20230620162913589.png" src="_images/image-20230620162913589.png" />
<p class="caption"><span class="caption-number">Fig. 130 </span><span class="caption-text">image-20230620162913589</span><a class="headerlink" href="#id18" title="Permalink to this image">¶</a></p>
</div>
</div>
</div>
<div class="section" id="creeping-crud">
<h2>9.2 渐长的积垢(creeping crud)和无偏舍入的神话<a class="headerlink" href="#creeping-crud" title="Permalink to this heading">¶</a></h2>
<p>IEEE
二进制浮点数中有四种“舍入模式”:向上舍入、向下舍入、向零舍入和最接近偶数舍入。
它们的同义词分别是:向无穷大舍入、向负无穷大舍入、截断舍入和无偏舍入。</p>
<p>如果我们可视化向上舍入,三角形左边是精确值,经过一个计算step后,真正的解包被替换为向正无穷靠近1个ulp间隔的精确值。用十进制数学舍入<span class="math notranslate nohighlight">\(13 \div 6=2.1666….\)</span>
会向上舍入到3.如果我们是13除以-6会舍入到-2.如果我们的舍入误差是随机的,平均每一个step误差增加0.5ULP。</p>
<div class="figure align-default" id="id19">
<img alt="_images/image-20230620163505196.png" src="_images/image-20230620163505196.png" />
<p class="caption"><span class="caption-number">Fig. 131 </span><span class="caption-text">image-20230620163505196</span><a class="headerlink" href="#id19" title="Permalink to this image">¶</a></p>
</div>
<p>向下舍入就是前面说的温哥华证券交易所使用的模式。他们使用3位十进制数值,但是每次更新指数永远向下舍入。误差图就是上图的垂直镜像。</p>
<div class="figure align-default" id="id20">
<img alt="_images/image-20230620203457608.png" src="_images/image-20230620203457608.png" />
<p class="caption"><span class="caption-number">Fig. 132 </span><span class="caption-text">image-20230620203457608</span><a class="headerlink" href="#id20" title="Permalink to this image">¶</a></p>
</div>
<p>一些应用,比如信号处理,或是简单的计算机图形学,舍入模式没有看上去的那么糟糕,原因是每个数据item只有少量的数学运算操作,所以舍入误差不会累积起来。但是对于温哥华证券交易所,下图是累积误差的样子,假设每次舍入都是统计学独立的。</p>
<div class="figure align-default" id="id21">
<img alt="_images/image-20230620204117762.png" src="_images/image-20230620204117762.png" />
<p class="caption"><span class="caption-number">Fig. 133 </span><span class="caption-text">image-20230620204117762</span><a class="headerlink" href="#id21" title="Permalink to this image">¶</a></p>
</div>
<p>向零舍入舍入比上面两个模式容错性强,因为计算有相同的几率是正的或是负的误差。比如两个向量的点积<span class="math notranslate nohighlight">\(a_1b_1+a_2b_2+\cdots+a_nb_n\)</span>.
如果a和b的元素都以相同几率为正或负,那么舍入有一半是向上,一半是向下。</p>
<p>最常用的舍入模式是无偏差舍入,就是替换正确答案为半个ULP以内的浮点数。如果是平局(正好都半个ULP),那么选择最近的偶数。无偏舍入需要额外的硬件,和执行时间。但是结果看上去更好看些。</p>
<div class="figure align-default" id="id22">
<img alt="_images/image-20230620204805829.png" src="_images/image-20230620204805829.png" />
<p class="caption"><span class="caption-number">Fig. 134 </span><span class="caption-text">image-20230620204805829</span><a class="headerlink" href="#id22" title="Permalink to this image">¶</a></p>
</div>
<p>无偏舍入可以把平均误差减少到0.5到0.25个ULP之间。但是可以在任意方向。这就把我们带到了统计学家所说的随机运动问题。假设你多次抛掷一枚硬币,如果是正面你往前一步,反之后退一步。经过n次抛掷,你离开起点多少步。我们期望抛掷得到正面的平均数目是n/2,
但是会有些偏差,近似是一个钟形曲线,如下图</p>
<div class="figure align-default" id="id23">
<img alt="_images/image-20230620205805573.png" src="_images/image-20230620205805573.png" />
<p class="caption"><span class="caption-number">Fig. 135 </span><span class="caption-text">image-20230620205805573</span><a class="headerlink" href="#id23" title="Permalink to this image">¶</a></p>
</div>
<p>偏差是抛掷数量的平方根。</p>
<p>所以推论是无偏差舍入的累积误差在很多次计算累积后都是可以容忍的。</p>
<div class="figure align-default" id="id24">
<img alt="_images/image-20230620210101442.png" src="_images/image-20230620210101442.png" />
<p class="caption"><span class="caption-number">Fig. 136 </span><span class="caption-text">image-20230620210101442</span><a class="headerlink" href="#id24" title="Permalink to this image">¶</a></p>
</div>
<p>即使我们做1
billion(<span class="math notranslate nohighlight">\(10^9\)</span>)个加法,推导出来的ULP数目通常在<span class="math notranslate nohighlight">\(\pm\sqrt{10^9}\)</span>个0.25ULP,这大概是7906个ULP,如果是用单精度累积,一个ULP是<span class="math notranslate nohighlight">\(\frac{1}{8388608}\)</span>,
所以我们累积误差在<span class="math notranslate nohighlight">\(\frac{7906}{8388608}\)</span>,或者说是正确答案的0.001。</p>
<p>你接受这个说法吗?显然看上去是合理的推导。单精度可以表示高达<span class="math notranslate nohighlight">\(10^{38}\)</span>的数,而且有足够的小数来表达<span class="math notranslate nohighlight">\(10^9\)</span>大小的精确整数。</p>
<p>随机运动可以保护我们避免累积误差,对吗?</p>
<p>一点也不。 下面是一个简单的C程序试图累加1 billion次1</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span>#include < stdio.h >
float sumtester () {
float sum; int i;
sum = 0.0;
for (i = 0; i < 1000000000; i++) {
sum = sum + 1.0;
}
printf (“%f\n”, sum);
}
</pre></div>
</div>
<p>你能得到的结果是(用IEEE单精度浮点float)</p>
<p>16 777 216</p>
<p>结果小了60倍。并不是单精度浮点不能表示累加值那么大的数,那到底哪里出错了?</p>
<p>错误发生在假设舍入误差是独立的向上或是向下。舍入误差通常不是独立的,在上面求和程序中,他们一直是一个方向,向下。当和达到<span class="math notranslate nohighlight">\(2^{24}=16777216\)</span>后,一个ULP的宽度大于了1,所以加1什么都不能改变。最接近偶数舍入一直不停的把正确答案16
777 217舍入到16 777 216。</p>
<p>这样一个在长时间的计算中缓慢累积舍入误差的现象有一个别名叫“creeping
crud”
(渐长的积垢),但是如这个例子显示的那样,误差不一定总是像爬行一样累积的,有时候也是跑步一样迅速增长的。无偏舍入假的神话是基于设舍入误差是独立且随机地向上和向下的。<strong>这个假设并没有任何逻辑的基础</strong>,
例子程序显示了即便是简单的程序也不支持这个假设。</p>
<p>计算中一个常用的方法是蒙特卡洛仿真方法,就是通常要求累加随机数经过某函数变换后的值。如果你选择1
billion的0到1间的随机数,统计学说结果应该是0.5 billion.</p>
<p>试试看用单精度是怎么样的,结果还是16 777 216, 一点不接近500 000 000.
蒙特卡罗方法的一种应用是对股票投资组合的财务价值进行建模,并确定哪些股票被高估或低估。
想象一下,在就一项重大投资向客户提供建议时,由于无形的舍入误差而出现八倍偏差的后果!</p>
</div>
<div class="section" id="id4">
<h2>9.3 自动精度控制和简单的 unum 数学测试<a class="headerlink" href="#id4" title="Permalink to this heading">¶</a></h2>
<p>现在我们可以做 unum加法了,我们可以试验 unum 处理累积误差挑战的能力。
如果我们在前面的示例中使用可以模仿 IEEE 单精度的 {3, 5}
环境,这还不是一场公平的战斗。 unum
只需使用最小指数大小并根据需要调整小数来计算确切的答案,以表示每个整数加法而不进行四舍五入(毕竟小数部分可以高达32b,
而float只有24b)。 真正的问题是当 unums
必须将结果标记为不准确时会发生什么。 这比四舍五入好吗?</p>
<p>要研究该问题,请使用精度非常低的 {3, 3} 环境来放大该问题。 在 {3, 3}
环境中,可以表示最大为 512 的整数,但请注意我们将 1 的 unum 添加到 512
的 unum 会发生什么</p>
<div class="figure align-default" id="id25">
<img alt="_images/image-20230621084439329.png" src="_images/image-20230621084439329.png" />
<p class="caption"><span class="caption-number">Fig. 137 </span><span class="caption-text">image-20230621084439329</span><a class="headerlink" href="#id25" title="Permalink to this image">¶</a></p>
</div>
<p>这比浮点数更好; 相同精度的浮点数将准确地返回数字 512。
Unum至少警告我们,我们有一个“渐长的积垢”问题。 范围 (512,
1952)非常大,这表明 unum 可能会遇到区间运算的问题。 然而,由于 unum
环境记录数字本身的准确性,因此它们提供了使用以下规则自动检测、分析和纠正准确性损失的可能性</p>
<table border="2"><tr><td bgcolor="lightblue"><p>如果结果包含 maxreal 或 –smallsubnormal 作为其下限,或者 –maxreal
或smallsubnormal 作为其上限,则计算环境需要更大的 esizesize。
如果相对宽度大于设定的公差,则计算需要更大的fsizesize.</p>
</td></tr></table><p>由于无法准确表示 513,因此我们得到一个包含 513 的开区间。
这看起来像传统的区间算术,但 ubound 仅使用 22 位而不是 128
位,并且表达出了总和不等于 512 也不等于 514
的事实,而是严格介于这些边界之间的数字。 尝试再加1,ULP宽度扩展为4;
它仍然可以用 20 位 unum 有效地表达,但精度已下降到大约两位十进制小数:</p>
<div class="figure align-default" id="id26">
<img alt="_images/image-20230621092307613.png" src="_images/image-20230621092307613.png" />
<p class="caption"><span class="caption-number">Fig. 138 </span><span class="caption-text">image-20230621092307613</span><a class="headerlink" href="#id26" title="Permalink to this image">¶</a></p>
</div>
<p>了解了准确性如何丢失后,这里给出 10^9 求和问题的“比例模型”。这次只是循环
1000次,足以强制使用不精确的 unum:</p>
<div class="figure align-default" id="id27">
<img alt="_images/image-20230621092904911.png" src="_images/image-20230621092904911.png" />
<p class="caption"><span class="caption-number">Fig. 139 </span><span class="caption-text">image-20230621092904911</span><a class="headerlink" href="#id27" title="Permalink to this image">¶</a></p>
</div>
<p>以上缺点都可以由计算系统自动跟踪和纠正。 第一种情况的自动测试很容易;
如前所述,如果结果对于动态范围而言太小或太大,<strong>needmoreexpQ</strong>
函数将返回 True。 例如,给 maxreal/2 加 1 不会超出环境的范围。</p>
<div class="figure align-default" id="id28">
<img alt="_images/image-20230621095943725.png" src="_images/image-20230621095943725.png" />
<p class="caption"><span class="caption-number">Fig. 140 </span><span class="caption-text">image-20230621095943725</span><a class="headerlink" href="#id28" title="Permalink to this image">¶</a></p>
</div>
<p>但是将 1 加到 maxreal 会,因为表示和的唯一方法是使用开区间
<span class="math notranslate nohighlight">\((maxreal,\infty)\)</span>。</p>
<div class="figure align-default" id="id29">
<img alt="_images/image-20230621101239670.png" src="_images/image-20230621101239670.png" />
<p class="caption"><span class="caption-number">Fig. 141 </span><span class="caption-text">image-20230621101239670</span><a class="headerlink" href="#id29" title="Permalink to this image">¶</a></p>
</div>
<p>相对位宽如果是0.05就基本对应一个十进制数的精度。间隔(10,
11)达到了一个十进制精度,因为<span class="math notranslate nohighlight">\(\frac{11-10}{11+10}=0.047\)</span>
没有超过0.05。而间隔(9,
10)就达不到这个分界点,因为<span class="math notranslate nohighlight">\(\frac{10-9}{10+9}=0.052\)</span>, 略超过了。</p>
<p>计算 ubound u 的相对宽度的原型函数是 <strong>relwidth</strong>[u]。
理想情况下,计算机系统可以选择使用内置硬件计算相对宽度,从而监控每个计算而不减慢计算速度。
然后可以自动生成最佳环境设置的指导,并且程序员可以将它们明确地放置在源代码中。</p>
<p>对于结果的间隔“太大”问题,我们可以通过多种方式测量间隔的相对宽度。
以下方法可以很好地处理异常情况。 如果 g 是一般区间,其中 glo 是下限,ghi
是上限(我们忽略端点是开还是闭),那么相对宽度的一种定义是</p>
<div class="math notranslate nohighlight" id="equation-09-add-sub-unbias-round-0">
<span class="eqno">(34)<a class="headerlink" href="#equation-09-add-sub-unbias-round-0" title="Permalink to this equation">¶</a></span>\[\begin{split}\text { Relative width of } g= \begin{cases}
\infty & \text { if } g \text { is NaN, } \\
1 & \text { if }\left|g_{\mathrm{lo}}\right|=\infty \text { or } \left|g_{\mathrm{hi}}\right|=\infty, \\
0 & \text { if }\left|g_{\mathrm{lo}}\right|=0 \text { and }\left|g_{\mathrm{hi}}\right|=0 \\
\frac{\left|g_{\mathrm{hi}}-g_{\mathrm{lo}}\right|}{\left|g_{\mathrm{lo}}\right|+\left|g_{\mathrm{hi}}\right|} & \text{otherwise.}
\end{cases}\end{split}\]</div>
<p>如果 g 表示 NaN,则相对宽度被视为无限大。 如果 g
有无限大的端点,则相对宽度为 1。如果端点符号相反,底部实数的比率也将为
1。
(如果我们无法判断一个数字是正数还是负数,那么我们真的对它了解不多。)</p>
<p>回想一下关于准确性的“要求和让步”讨论(第 5.4.2 节)。
应该允许计算机用户提出要求,例如“我的结果需要四位小数的精确度”;
这也是一种让步,因为这意味着计算机可以通过不计算超过四位小数的精度来节省能量和时间。
但计算机用户也不应该指定计算自始至终都以一定的精度进行,因为这把手段当成目的了。
正如计算机用户可以使用 <strong>smartunify</strong>
设置压缩数字的策略一样,用户可以设置环境变量 <strong>relwidthtolerance</strong>
来指定答案所需的准确性。 <strong>needmorefracQ</strong>
函数然后使用该容差来检测计算是否需要更大的 fsizesize。
相对宽度容差还设置了 fsizesize
的下限,因为必须至少有足够的分数位来表达所需的精度。 将
<strong>relwidthtolerance</strong> 设置为 0.005 表示我们想要两位小数的精度,这在 {3,
3} 环境中是可能的:</p>
<div class="figure align-default" id="id30">
<img alt="_images/image-20230621132754304.png" src="_images/image-20230621132754304.png" />
<p class="caption"><span class="caption-number">Fig. 142 </span><span class="caption-text">image-20230621132754304</span><a class="headerlink" href="#id30" title="Permalink to this image">¶</a></p>
</div>
<p>显然[10, 11]只有一位精度,需要更多bit</p>
<div class="figure align-default" id="id31">
<img alt="_images/image-20230621132851277.png" src="_images/image-20230621132851277.png" />
<p class="caption"><span class="caption-number">Fig. 143 </span><span class="caption-text">image-20230621132851277</span><a class="headerlink" href="#id31" title="Permalink to this image">¶</a></p>
</div>
<p>而间隔(500,
504)在{3,3}环境中只有一个ULP宽度,相对宽度约0.004,所以无需提升精度。</p>
<div class="figure align-default" id="id32">
<img alt="_images/image-20230621133045237.png" src="_images/image-20230621133045237.png" />
<p class="caption"><span class="caption-number">Fig. 144 </span><span class="caption-text">image-20230621133045237</span><a class="headerlink" href="#id32" title="Permalink to this image">¶</a></p>
</div>
<p>这种方法的流程图如下所示,其中蓝色显示的部分可以由程序员请求或自动执行。
该策略与用于保护长时间运行的超级计算任务免受硬件故障影响的检查点重启方法非常相似,这也可以在应用程序级别或由操作系统自动完成。
使用这些工具,我们将再次尝试求和,但让计算机自动管理精度和动态范围。
我们可以等待最终的总和,然后让计算机检查是否需要更多的指数或分数,或者我们可以全程监控计算,并在检测到需要提升精度时立即重新启动。
连续监控消除了继续进行明显“偏离轨道”的计算所浪费的时间。</p>
<div class="figure align-default" id="id33">
<img alt="_images/image-20230621144551097.png" src="_images/image-20230621144551097.png" />
<p class="caption"><span class="caption-number">Fig. 145 </span><span class="caption-text">image-20230621144551097</span><a class="headerlink" href="#id33" title="Permalink to this image">¶</a></p>
</div>
<p>下面是一个软件实现此类监控的程序,我们首先以 {2, 2}
环境开始,让计算机决定是否需要更多位。
每当计算机检测到环境需要提升时,一些老式的“跳转”语句就会重新开始计算。
这些语句按相应的流程图颜色进行颜色编码,自动监控显示为蓝色。</p>
<div class="figure align-default" id="id34">
<img alt="_images/image-20230621144951071.png" src="_images/image-20230621144951071.png" />
<p class="caption"><span class="caption-number">Fig. 146 </span><span class="caption-text">image-20230621144951071</span><a class="headerlink" href="#id34" title="Permalink to this image">¶</a></p>
</div>
<p>答案是精确的了,那目前到了什么样的环境呢?</p>
<div class="figure align-default" id="id35">
<img alt="_images/image-20230621145042415.png" src="_images/image-20230621145042415.png" />
<p class="caption"><span class="caption-number">Fig. 147 </span><span class="caption-text">image-20230621145042415</span><a class="headerlink" href="#id35" title="Permalink to this image">¶</a></p>
</div>
<p>由于我们只要求两位小数的精度,relwidthtolerance 为 0.005,因此 [991,
1010] 中包含的任何 ubound 的相对宽度测试都将通过。
当期望一个完全准确的结果是合理的,就像这里一样,程序员可以将
relwidthtolerance 设置为零。</p>
<p>这个流程是这样进行的:初始设置的{2,2}环境只允许最大4个指数位和4个小数位。和最高不超过32.
当到了后再加一就得到不精确数,范围在(32, 34).
计算其相对宽度是<span class="math notranslate nohighlight">\(\frac{1}{33}\)</span>
显然是大于<span class="math notranslate nohighlight">\(0.005=\frac{1}{200}\)</span>。所以环境就自动提升到{2,3},
累加又重新开始,稍微浪费了一些计算。</p>
<p>第二次尝试的时候,加法结果超过了maxreal, 在{2,3}环境中是510.
所以再加1的时候就发现结果落在<span class="math notranslate nohighlight">\((510, \infty)\)</span>
这说明需要更多的指数。于是提升环境到{3, 3},再次重新启动计算。</p>
<p>第三次尝试,当加法的和达到512这个精确值,接着就是不精确了,
ULP宽度开始逐渐累积:</p>
<p>512, (512,514), (512, 516), (512, 518)</p>
<p>这时候(512,
518)相对宽度大约是0.0058,超过门限,通过了<strong>needmorefracQ</strong>测试,环境提升到{3,
4}. 这次可以一直做到最后得到的是精确的答案。</p>
<p>这个例子说明了一些数值分析可以被自动化,如果能让精度的丢失可以被看见。</p>
</div>
</div>
</div>
<div class="side-doc-outline">
<div class="side-doc-outline--content">
<div class="localtoc">
<p class="caption">
<span class="caption-text">Table Of Contents</span>
</p>
<ul>
<li><a class="reference internal" href="#">9 加减法和无偏差舍入的迷</a><ul>
<li><a class="reference internal" href="#id2">9.1 重新学习加法表…对实数</a><ul>
<li><a class="reference internal" href="#id3">9.1.1 例子和测试数据搬移量</a></li>
<li><a class="reference internal" href="#ubound">9.1.2 三维可视化ubound的加法</a></li>
<li><a class="reference internal" href="#unum">9.1.3 unum加减法的硬件实现</a></li>
</ul>
</li>
<li><a class="reference internal" href="#creeping-crud">9.2 渐长的积垢(creeping crud)和无偏舍入的神话</a></li>
<li><a class="reference internal" href="#id4">9.3 自动精度控制和简单的 unum 数学测试</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<div class="clearer"></div>
</div><div class="pagenation">
<a id="button-prev" href="08_comparison_operations.html" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--colored" role="botton" accesskey="P">
<i class="pagenation-arrow-L fas fa-arrow-left fa-lg"></i>
<div class="pagenation-text">
<span class="pagenation-direction">Previous</span>
<div>8 比较操作</div>
</div>
</a>
<a id="button-next" href="10_mul_div.html" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--colored" role="botton" accesskey="N">
<i class="pagenation-arrow-R fas fa-arrow-right fa-lg"></i>
<div class="pagenation-text">
<span class="pagenation-direction">Next</span>
<div>10 乘法和除法</div>
</div>
</a>
</div>
</main>
</div>
</body>
</html>