《编写高质量代码:改善c程序代码的125个建议》——建议12-1:用倒数相乘来实现除法运算

简介:

本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第2章,建议12-1,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

建议12-1:用倒数相乘来实现除法运算

何为倒数相乘?其实很简单,它的核心思想就是利用乘法来代替实现除法运算。例如,在IA-32处理器中,乘法指令的运算速度比除法指令要快4~6倍。因此,在某些情况下尽量使用乘法指令来代替除法指令。
那么,我们该如何利用乘法来代替实现除法运算呢?原理就是被除数乘以除数的倒数,用公式表现为:

x/y=x*(1/y)

例如,计算10/5,可以根据公式x/y=x*(1/y)这样来计算:

10/5=10*(1/5)=10*0.2=2

在实际应用中,一些编译器也正是基于这个原理才得以将除法运算转换为乘法运算的。现在我们来看一个除法运算示例,如代码清单2-1所示。

代码清单2-1 除法运算示例
#include <stdio.h>
int main(void)
{
    int x = 3/2;
    float y = 3.0/2.0;
    printf("3/2 = %d\r\n3.0/2.0 = %1.1f\n",x,y);
    return 0;
}

代码清单2-1的运行结果如图2-1所示。


1347618f15d71dfa60ed947aa0cc5ad08d8f7494

通过代码清单2-1可以看出,很明显没能充分考虑到浮点类型。另外,在C语言中,一般情况下1除以任何数其结果皆为0。那么怎样才能解决这个问题呢?编译器采用了一种称为“定点运算”(fixed-point arithmetic)的
方法。
那么何为定点运算,定点运算有什么特点呢?
前面已经阐述过,由于计算机表示实数时为了在固定位数内能表示尽量精确的实数值,分配给表示小数部分的位数并不是固定的,也就是说“小数点是浮动的”,因此计算机表示的实数数据类型也称为浮点数。
相对于“小数点是浮动的”来讲,定点运算根据字面意思来理解就是“小数点是固定的”。有了定点运算,表示小数时不再用阶码(exponent component,即小数点在浮点数据类型中的位置),而是要保持小数点的位置固定不变。这和硬件浮点数机制截然不同,硬件浮点数机制是由硬件负责向整数部分和小数部分分配可用的位数。有了这种机制,浮点数就可以表示很大范围的数——从极小的数(在0~1的实数)到极大的数(在小数点前有数十个0)。这种小数的定点表示法有很多优点,尤其能极大地提高效率。当然,作为代价,同样也必须承受随之而来的精度上的损失。
对于定点数表示法(fixed-point),相信大家并不陌生。所谓定点格式,即约定机器中所有数据的小数点位置是固定不变的。在计算机中通常采用两种简单的约定:将小数点的位置固定在数据的最高位之前(即定点小数),或者固定在最低位之后(即定点整数)。
其中,定点小数是纯小数,约定的小数点位置在符号位之后、有效数值部分的最高位之前。若数据x的形式为x=x0x1x2…xn(其中x0为符号位,x1,…,xn是数值的有效部分,也称为尾数,x1为最高有效位),则在计算机中的表示形式为:

4acb2541aff1e471e2a7b79f5522fd9cc3fbe239

一般说来,如果最末位xn=1,前面各位都为0,则数的绝对值最小,即|x|min=2-n;如果各位均为 1,则数的绝对值最大,即|x|max = 1-2-n。因此定点小数的表示范围是:
2-n≤|x|≤1-2-n

定点整数是纯整数,约定的小数点位置在有效数值部分最低位之后。若数据x的形式为x = x0x1x2…xn(其中x0为符号位,x1,…,xn是尾数,xn为最低有效位),则在计算机中的表示形式为:


<a href=https://yqfile.alicdn.com/baf6213179facf697a3ec8d28a953eccf2215f66.png" >

由此可知,定点整数的表示范围是:
1≤|x|≤2n-1

当数据小于定点数能表示的最小值时,计算机将它作0处理,称为下溢;当数据大于定点数能表示的最大值时,计算机将无法表示,称为上溢,上溢和下溢统称为溢出。
当计算机采用定点数表示时,对于既有整数又有小数的原始数据,需要设定一个比例因子,数据按该比例缩小成定点小数或扩大成定点整数再参加运算。在运算结果中,根据比例因子,将数据还原成实际数值。若比例因子选择不当,往往会使运算结果产生溢出或降低数据的有效精度。

相关文章
|
27天前
|
安全 编译器 程序员
【C++ 编译时有理算术】理解 C++编译时有理数运算:原理、实践与应用
【C++ 编译时有理算术】理解 C++编译时有理数运算:原理、实践与应用
67 1
|
10月前
|
Python
制作实现加减乘除运算的简单计算器
制作实现加减乘除运算的简单计算器
79 0
|
C语言
用函数编程实现输出 m~n之间所有素数,并求和,m和n由键盘输入。(c语言)
用函数编程实现输出 m~n之间所有素数,并求和,m和n由键盘输入。(c语言)
479 0
|
存储 算法 C语言
【Python 百炼成钢】 小学生算术、阶乘的精确值、孪生素数、6174问题
【Python 百炼成钢】 小学生算术、阶乘的精确值、孪生素数、6174问题
173 0
【Python 百炼成钢】 小学生算术、阶乘的精确值、孪生素数、6174问题
|
程序员 C++ Python
程序员数学基础【三、取模运算(取余运算功能重叠部分)】(Python版本)
程序员数学基础【三、取模运算(取余运算功能重叠部分)】(Python版本)
223 0
程序员数学基础【三、取模运算(取余运算功能重叠部分)】(Python版本)