(1)float,double类型的存储
在Java中,`float`和`double`都是用来表示浮点数的数据类型,它们在内存中的存储方式略有不同。
1. **float(单精度浮点数)**:
- 在Java中,`float`占用4个字节(32位),其中1位用于表示符号(正负号),8位用于指数,剩下的23位用于尾数。
- 单精度浮点数的范围大约在1.4E-45到3.4E+38之间,精度大约在6到7位有效数字。
- `float`类型的字面量可以使用后缀`f`或`F`来表示,例如:`3.14f`。
2. **double(双精度浮点数)**:
- 在Java中,`double`占用8个字节(64位),其中1位用于表示符号(正负号),11位用于指数,剩下的52位用于尾数。
- 双精度浮点数的范围大约在4.9E-324到1.8E+308之间,精度大约在15到16位有效数字。
- `double`类型的字面量可以使用后缀`d`或`D`表示(通常情况下可以省略),例如:`3.14`。
浮点数的精度损失问题和比较相等
浮点数在内存中是以二进制存放的,故无法模拟出完全的精度,如0.1,在内存中应该是一个无线循环小数。
#include <stdio.h>
int main() {
double num = 0.1;
// 使用 %A 格式控制符输出浮点数以十六进制的形式
printf("Number in hexadecimal format: %A\n", num);
// 使用 %E 格式控制符输出浮点数以科学计数法的形式
printf("Number in scientific notation: %E\n", num);
return 0;
}
输出为:
Number in hexadecimal format: 0X1.999999999999AP-4
Number in scientific notation: 1.000000E-01
比较相等问题 , 两个浮点数极其相近时,就只能通过限定精度来比较了。
如:
#include<stdio.h>
int main()
{
double num1 = 0.1;
double num2 = 0.2-0.1;
double epsilon = 1e-10;
if(fabs(num2 - num1) > epsilon)
{
printf("num2 == num1");
}
{
printf("num2 != num1");
}
}
而比较两个浮点数的大小,编译期间就能确定,这是因为字面量就能看出:
#include<iostream>
int main()
{
constexpr double num1 = 0.111111;
constexpr double num2 = 0.111112;
if(num2>num1)
{
std::cout<<"num2>num1"<<strd::end;
}
else
{
std::cout<<"num1>num2"<<strd::end;
}
return 0;
}
overflow和underflow
计算机只能使用有限的bit来描述数字,因此当被描述的数字需要超多的bit位,而计算机的bit位不够时,计算机就不能准确地表示这些数字。
例如,当一个数逼近0时,如0.00000000001,计算机就会就会视作0,但没有存储作用了,这叫underflow,相反的问题为overflow。
有趣的代码:
#include<iostream>
using namespace std;
int main()
{
unsigned int num = 4294967295;
cout<<num+1<<endl;
int num1 = 2147483647+1;
if(num1>0)
{
cout<<"num>0"<<endl;
}
else
{
cout<<"num<0"<<endl;
}
}
size_t
size_t 是一种用于表示内存大小的数据类型,通常在 C 和 C++ 编程语言中使用。它是无符号整数类型,其大小足以容纳任何可能的数组索引或对象大小。size_t 的大小通常与指针的大小相同,因此在 32 位系统上通常是 4 字节,在 64 位系统上通常是 8 字节。
建议使用size_t