除以二
在数学中,除以二是一种运算动作,即被除数的除数(分母)是二、或乘以二分之一的动作,又可称为半分(dimidiation)或平分(halving)[1]。最早将除以二视为一种独立运算的是古埃及人,其用于古埃及乘法算法中的一个基本步骤[2]。一直到近代,除以二都有被单独当作为一种运算方式看待的情况[3][4]。而在现代电脑程式设计中,由于大部分的情况下,除以二可以使用逻辑位移运算取代,因此也用于编译器最佳化的技术中[5]。
历史
将除以二视为一个特殊的运算方式来处理乘法及除法的做法,最早可以追溯到古埃及人,其将除以二作为古埃及乘法算法中的一个基本步骤[2]。 一直到十六世纪,仍有一些数学家将除以二视为一个独立的运算方式[3][4]。 而在十进制算术、计算机科学的二进制及其他偶数进制算术中,除以二的计算相较于被除数的除数为其他数的除法而言,相对简单,因此在现代的计算机程序设计中,除以二也会被视为一个独立的运算子[5]。
二进制
在二进制算术中,除以二可以透过移位运算中的右移运算子来完成,即将二进制数中的每一位全部都向右移动一位,此技术应用于编译器最佳化中的强度折减技术[6]。例如将105除以二,先将105表示为二进制,即1101001,接着将所有位元向右移一位,溢位的部分1被舍弃,即得到商110100,对应的十进制数值为52。类似地,此操作可以套用到所有除以二的正整数次方的情形,当被除数的除数(分母)为 时,其做法为将该数的所有位数右移 位来完成,例如欲将二十四除以八,24在二进制中计为11000,而8为2的三次幂,将11000向右位移3位得11,十进制为3,则得到商为3,即完成 的运算。由于位移运算通常比除法来得快,因此以这种透过位移运算取代部分除法运用在编译器最佳化中是有帮助的[5]。但是,出于程式码的可移植性和可读性的考虑,通常仍然会在程式码中以除法表示,替换为移位运算应由编译器来完成[7]。不过,在有符号数处理中,上述做法并不能确保总是正确。一般逻辑右移一位可以将该数除以二,若除不尽总是会向下取整,但在某些编程语言中,有符号二进制整数的除法会向0舍入,也就是说,若一整数是负的,除不尽的状况将会向上取整。
除以2k
逻辑右移可以处理除数(或分母)为任意二的幂的除法,即除以 。例如除以四、除以八等。更一般地,在特定底数 的进位制中,除数(或分母)为任意 的除法(k为整数)皆可以透过将数字位数向右移k位来完成。例如除以十,由于普遍的数字计法是透过十进制表达,因此可以直接将数字位数向右移1位来完成除以十的操作。例如230除以十,将230向右移一位,得23,即 。
二进制浮点数
在二进制浮点数算术中,在不要求结果不为非正规化数的情况下,由于其是由二进制表示,因此可透过将浮点数科学记号的指数部分减一来完成除以二的动作[8]。许多编程语言会单独专门为浮点数提供除以二的幂之函数,例如Java有提供一个名为java.lang.Math.scalb
的函数来计算二的幂之比[9];而C语言也有类似功能的函数,例如ldexp
[10]。
十进制
在十进制中,可透过下列算法将任意整数除以二,其也可以作为定义底数为偶数之进位制中将任意数除以二的模型。其做法如下:
- 写下整数N,并于左边补上1个0。
- 针对N的每一个位数,根据下列表格写下数字则可得到除以二的商。
第一位数为 | 偶数 | 偶数 | 偶数 | 偶数 | 偶数 | 奇数 | 奇数 | 奇数 | 奇数 | 奇数 |
---|---|---|---|---|---|---|---|---|---|---|
下一位数 | 0 或 1 | 2 或 3 | 4 或 5 | 6 或 7 | 8 或 9 | 0 或 1 | 2 或 3 | 4 或 5 | 6 或 7 | 8 或 9 |
写下 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
例如: 1738除以2=?
- 写下 01738。
- 01:偶数位数0后面跟着1,写下0;
- 17:奇数位数1后面跟着7, 写下8;
- 73:奇数位数7后面跟着3, 写下6;
- 38:奇数位数3后面跟着8, 写下9;
- 商为0869。
从示例中可以看出0是偶数。此外,若N的最后一位是奇数,则需再将0.5加到结果中。
奇偶性
其他用途
除以二可以用于某些速算法,例如某数乘以五可以透过先将该数除以二再乘以十来完成[11],例如25乘以五,首先将25除以2得12.5,再乘以10得到结果为125。
参见
参考文献
- ^ Steele, Robert, The Earliest arithmetics in English, Early English Text Society 118, Oxford University Press: 82, 1922.
- ^ 2.0 2.1 Chabert, Jean-Luc; Barbin, Évelyne, A history of algorithms: from the pebble to the microchip, Springer-Verlag: 16, 1999, ISBN 978-3-540-63369-3.
- ^ 3.0 3.1 Jackson, Lambert Lincoln, The educational significance of sixteenth century arithmetic from the point of view of the present time, Contributions to education 8, Columbia University: 76, 1906.
- ^ 4.0 4.1 Waters, E. G. R., A Fifteenth Century French Algorism from Liége, Isis, 1929, 12 (2): 194–236, JSTOR 224785, doi:10.1086/346408.
- ^ 5.0 5.1 5.2 Wadleigh, Kevin R.; Crawford, Isom L., Software optimization for high-performance computing, Prentice Hall: 92, 2000, ISBN 978-0-13-017008-8.
- ^ Granlund, Torbjörn; Peter L. Montgomery. Division by Invariant Integers Using Multiplication (PDF). [2019-04-22]. (原始内容存档 (PDF)于2019-06-06).
- ^ Hook, Brian, Write portable code: an introduction to developing software for multiple platforms, No Starch Press: 133, 2005, ISBN 978-1-59327-056-8.
- ^ Computer Architecture and Organization: Design Principles and Applications. Tata McGraw-Hill. 2004: 170 [2019-04-23]. ISBN 9780070532366. (原始内容存档于2019-08-18).
- ^ Math.scalb. Java Platform Standard Ed. 6. [2009-10-11]. (原始内容存档于2009-08-29).
- ^ Programming languages — C, International Standard ISO/IEC 9899:1999, Section 7.12.6.6.
- ^ 优等生必学的速算技巧大全. 清华大学出版社. 2018 [2019-04-24]. ISBN 9787302463214. (原始内容存档于2019-08-18).