关于double和float精度丢失的问题
起因
这个问题,我记得我是在五年级的时候就有了,情况大概如下
现在,你需要将π放进一个变量中,需要保留到小数点后100位
过程
完成代码
第一次代码
当时,我想着,不是so easy嘛,然后编写出了如下代码
#include <bits/stdc++.h>
using namespace std;
int main(){
float x=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
cout<<x;
}然后,我怀着激动的心情,颤抖的手,内心OS:马上就可以AK了!哈哈哈哈!!! ,但是,现实给我了种种一拳
* 正在执行任务: C:\SOFTWARE\Dev-Cpp\MinGW64\bin\g++.EXE -Wall -Wextra -g3 -std=c++23 e:\double.cpp -o e:\output\double.exe
PS E:\output> & .\'double.exe'
3.14159我:
?
What FUCK???
这感觉不太对啊,这输出怎么能这样子
哦!我忘了,还有double!
使用double完成
然后编写出了如下代码
#include <bits/stdc++.h>
using namespace std;
int main(){
double x=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
cout<<x;
}一键运行:
* 正在执行任务: C:\SOFTWARE\Dev-Cpp\MinGW64\bin\g++.EXE -Wall -Wextra -g3 -std=c++23 e:\double.cpp -o e:\output\double.exe
PS E:\output> & .\'double.exe'
3.14159?
没保存吗
Try again
* 正在执行任务: C:\SOFTWARE\Dev-Cpp\MinGW64\bin\g++.EXE -Wall -Wextra -g3 -std=c++23 e:\double.cpp -o e:\output\double.exe
PS E:\output> & .\'double.exe'
3.14159What FUCK?
怎么还是这样?
那时候我情绪崩溃了,不知道咋回事
然后,我突然想起来了保留小数点的方法!即setprecision
使用setprecision的方法完成
然后写出了如下代码
#include <bits/stdc++.h>
using namespace std;
int main(){
double x=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
cout<<setprecision(100)<<x;
}嘿嘿嘿,兄弟们,终于可以AK了!!!
* 正在执行任务: C:\SOFTWARE\Dev-Cpp\MinGW64\bin\g++.EXE -Wall -Wextra -g3 -std=c++23 e:\double.cpp -o e:\output\double.exe
PS E:\output> & .\'double.exe'
3.141592653589793115997963468544185161590576171875az
好像确实精确了亿点,但没有完全精确吧?
怀疑人生中。。。
哦!还有printf!!!
使用printf的方法完成
#include <bits/stdc++.h>
using namespace std;
int main(){
double x=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
printf("%.100lf",x);
}这下总不能错了,printf可是C语言的,怎么可能错??
可是...
现实又给我了重重一锤
* 正在执行任务: C:\SOFTWARE\Dev-Cpp\MinGW64\bin\g++.EXE -Wall -Wextra -g3 -std=c++23 e:\double.cpp -o e:\output\double.exe
PS E:\output> & .\'double.exe'
3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000我是不配学编程吗???
为什么显示总是这么打击我
呜呜呜呜呜呜呜呜
呜呜呜呜呜呜
现在的情况
2024年,Deepseek-R1模型发布
我草,牛逼!
2025年9月24日,一学校老师向我询问此问题,又够引了我的兴趣
- IEEE 754 浮点数标准
计算机使用固定的位数来存储浮点数:
- float(单精度):32位,约6-7位有效数字
- double(双精度):64位,约15-16位有效数字
- long double:通常80位或128位
- double 的存储结构
double 使用64位存储:
- 1位符号位
- 11位指数位
- 52位尾数位
这意味着 double 只能精确表示大约15-16位十进制数字。
以上内容来自Deepseek-R1
EMM,似懂非懂,但是大概了解了
浮点数在计算机中以二进制分数形式存储,无法精确表示所有十进制小数。
以上内容来自Deepseek-R1
《二进制分数》
我嘞个二进制分数
依旧是补码,对吧???
二进制存储原理
double 的52位尾数只能表示有限精度的分数:
3.141592653588888... = 无法用有限二进制精确表示计算机找到最接近的可表示二进制分数,这就是你看到的"奇怪"数字。
以上内容来自Deepseek-R1
我的评价:六百六十六
- 浮点数都是近似值
- 不要用 == 直接比较浮点数
- 需要高精度时使用特殊库或整数运算
以上内容来自Deepseek-R1
我的评价:近似值???
现在看来,我为什么不使用先乘再除呢?
#include <bits/stdc++.h>
using namespace std;
int main(){
unsigned long long x=31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
cout<<double(x/99);
}于是,我就发现了
* 正在执行任务: C:\SOFTWARE\Dev-Cpp\MinGW64\bin\g++.EXE -Wall -Wextra -g3 -std=c++23 e:\double.cpp -o e:\output\double.exe
e:\double.cpp:5:26: warning: integer constant is too large for its type
5 | unsigned long long x=31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PS E:\output> & .\'double.exe'
1.07941e+17哦对对对对对对对,范围啊,我草
奇怪了,为什么我们不使用高精度数组呢?
使用数组
#include <bits/stdc++.h>
using namespace std;
int main(){
string x="31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
cout<<x;
}运行!
PS E:\output> & .\'double.exe'
31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679耶!成功!
完
致谢
此处评论已关闭