一次做题笔记
洛谷的一道50000个浮点数之和题目
内容涉及到long double,小数转unsigned long long
第一次是这么做的
直接声明两个long double变量, 为什么不是double?
因为似乎double只有大约17位有效数字, 而long double精度更高
代码是这样的
#include <bits/stdc++.h>
using namespace std;
int main()
{
long double a, b = 0;
while(scanf("%Lf", &a) != EOF) {
b += a;
}
printf("%.5Lf", b);
}
只通过了80%的样例, 为什么会这样呢?
说实话我也不知道, 精度的原因?
第二次, 看了题解之后是这么做的
把每次的a都乘1e6, 结果又除以1e6
P.S. 因为题目说了每个数据不超过小数后6位(我刚开始遗漏了)
我把乘1e6换成1e5, 1e7…1e16都错了部分样例
这是为什么?我还没搞懂。不是说long double精度够了吗? 把它的位数提为整数和还是小数有什么不一样吗?
我果然还是孤陋寡闻
这是我的代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
long double a, b = 0;
while(scanf("%Lf", &a) != EOF) {
b += a*1e6;
}
printf("%.5Lf", b/1e6);
}
题解中那个人的思路就是这样了, 不过他用了一种递归主函数的方法来读取数据
我觉得值得学习
#include<cstdio>
long double a,sum;//long double 保证精度没毛病
int main()
{
if(scanf("%Lf",&a)!=EOF)
{
sum+=a*1000000;//去除小数部分,直接乘,变成整数
main();//核心代码
}
else printf("%.5Lf",sum/1000000);//除回来
return 0;
}
第三种, 还是题解中别人的代码
他没用long double, 而是用了unsigned long long, 根据题目提供的数据范围, unsigned long long 刚好够用, 或许这是题目故意卡的数据
思路是: 把读取的每一个double扩大变为unsigned long long, 相加后四舍五入, 外加格式控制
这种思路或者说思维方式值得借鉴
#include <bits/stdc++.h>
using namespace std;
int BASE=1e6;
unsigned long long sum=0;
double term;
int main(int argc, char const *argv[])
{
while(scanf("%lf",&term)!=EOF)
{
term*=BASE;//最多六位小数,转成整数
sum+=(unsigned long long)term;
}
//要求打印5为小数,去掉最后一位
if(sum%10>=5) sum=sum/10+1;
else sum=sum/10;
BASE/=10;
//%05llu让不足五位小数的部分用0补全
printf("%llu.%05llu\n",sum/BASE,sum%BASE);
return 0;
}
可见,解决问题的方法可以有很多种
其实做题最重要的不是做出题目来, 而是在做题的过程中学会思考,运用所学的知识从各种方面思考解决问题,锻炼自己的思维能力。