c++ double类型存储

本文详细解析了C/C++中float与double的存储结构,包括符号位、指数位和尾数位的作用,以及如何根据这些位数计算浮点数的精度。同时,文章还解释了float和double在内存中的具体存储方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在C/C++中float是32位的,double是64位的,两者在内存中的存储方式和能够表示的精度均不同,目前C/C++编译器标准都遵照IEEE制定的浮点数表示法来进行float,double运算。

无论是float还是double,在内存中的存储主要分成三部分,分别是:

(1)符号位(Sign):0代表正数,1代表负数

(2)指数位(Exponent):用于存储科学计数法中的指数部分,并且采用移位存储方式

(3)尾数位(Mantissa):用于存储尾数部分

 

对于两者在内存中的存储结构,如下图所示:

 

    数字float 9.125在十进制中用科学计算的方式表示为9.125*10^0  ,但是在计算机中,计算机只认识0和1,所以在计算机中是按照科学计算的二进制的方式表示的:

9的二进制表示为1001

0.125的二进制表示为0.001

所以9.125的表示成1001.001  将其表示成二进制的科学计数方式为 1.001001*2^3 

 

在计算机中,任何一个数都可以表示成1.xxxxxx*2^n 这样的形式,

其中xxxxx就表示尾数部分,n表示指数部分

其中,因为最高位橙色的1这里,由于任何的一个数表示成这种形式时这里都是1,所以在存储时实际上并不保存这一位,这使得float的23bit的尾数可以表示24bit的精度,double中52bit的尾数可以表达53bit的精度。

 

    对于float型数据,可以精确到小数点后几位呢?当然,学过c的同学会说float能够精确到小数点后6位,但这是怎么的来的呢?下面做一点解释:

    十进制中的9,在二进制中的表示形式是1001,这里也就告诉我们,表示十进制中的一位数在二进制中需要4bit,所以我们现在float中具有24bit的精度,所以float在十进制中具有24/4=6,所以在十进制里,float能够精确到小数点后6位。同理,具有53bit精度的double类型能够精确到小数点后13位。

    对于float类型,他的指数部分有8bit,可以表示-127~128,但是这里采用了移位存储的方式(对这个概念不太清楚),在存储指数时数据的基数是127,而不是0,。例如上面的9.125,其二进制的指数部分为3,所以在存储时实际上存的是127+3=130。(130的二进制表示为10000010)

最终根据上面图中float的存储结构可以知道,实际上9.125在计算机中:

上面的二进制数转换成十六进制后表示形式为:01000001 00010000 00000000 00000000 --> 41 10 00 00

实际上在X86计算机中,采用的是小端存储方式,即低地址存储低位数据,高地址存储高位数据。

所以数据应该是这样存储的:

对于double类型的存储方式实际上和float是类似的,只是存储的位数不同,在原理上都是一样的。

### 关于C++中`double`类型的减法运算 在C++中,`double`类型是一种双精度浮点数类型,用于表示实数。当涉及到`double`类型的减法运算时,需要注意一些细节和潜在问题。 #### 1. `double`类型减法的基本语法 `double`类型的减法与其他数值类型相同,遵循标准的算术运算规则。以下是简单的示例代码: ```cpp #include <iostream> int main() { double a = 3.14; double b = 1.10; double result = a - b; std::cout << "Result of subtraction: " << result << std::endl; return 0; } ``` 此代码展示了两个`double`变量之间的简单减法操作[^1]。 --- #### 2. 浮点数精度问题 由于计算机内部存储浮点数的方式基于二进制表示,某些十进制小数无法精确表示为有限长度的二进制形式。这可能导致计算结果中的微小误差。例如: ```cpp #include <iostream> using namespace std; int main() { double a = 1.11; double b = 2.22; double c = b - a; cout.precision(17); // 设置更高的输出精度 cout << "Exact Result: " << c << endl; return 0; } ``` 运行以上代码可能会显示如下结果: ``` Exact Result: 1.1100000000000001 ``` 尽管最终结果显示为`1.11`,但实际上其内部值可能略有偏差。这是因为浮点数的二进制表达方式引入了舍入误差[^2]。 为了应对这种问题,可以采用以下几种策略之一: - **设置较低的有效位数**:通过控制输出流的小数位数减少视觉上的差异。 - 使用专门设计的数据结构或库(如高精度数学库),以避免此类错误的影响。 --- #### 3. 结合分数类处理更复杂的场景 如果希望更加精准地完成涉及分数的操作,则可以通过自定义类并重载运算符的方式来实现无损计算。下面展示了一个简化版的例子,其中包含了对分数相减的支持: ```cpp #include <iostream> using namespace std; class Fraction { private: int numerator_; int denominator_; public: Fraction(int num, int den) : numerator_(num), denominator_(den) {} void simplify() { int gcd_val = __gcd(numerator_, denominator_); numerator_ /= gcd_val; denominator_ /= gcd_val; } friend ostream& operator<<(ostream&, const Fraction&); Fraction operator-(const Fraction&) const; }; Fraction Fraction::operator-(const Fraction& other) const { int new_num = (this->numerator_ * other.denominator_) - (other.numerator_ * this->denominator_); int new_denom = this->denominator_ * other.denominator_; Fraction res(new_num, new_denom); res.simplify(); return res; } ostream& operator<<(ostream& os, const Fraction& frac){ os << frac.numerator_ << "/" << frac.denominator_; return os; } int main(){ Fraction f1(3, 4); Fraction f2(1, 2); Fraction diff = f1 - f2; cout << "Difference between fractions is: " << diff << endl; return 0; } ``` 在这个例子中,创建了一个名为`Fraction`的新类,并实现了对其成员函数`operator-()`的重新定义以便支持两份数字间的差额计算过程[^3]。 --- ### 注意事项 - 当执行`double`类型的减法时,应始终意识到可能存在由浮点数引起的细微误差。 - 如果应用程序严格依赖高度准确的结果,则考虑利用整数代替浮点数或者借助第三方的大数运算库来进行必要的调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值