当前位置: 首页 > web >正文

浮点数精度问题(CSP38思考)

        CSP38的第一题,考到了浮点数的除法(当然考完发现其实也可以不涉及浮点数,直接转化为整型),我第一题一直卡到70、80分,故写下此文。


        浮点数的运算有精度损失问题,那么应该如何解决和避免呢?

        一个int类型变量乘以1.0,转化的是double型(64位系统下,8字节),如果乘以1.0f,那就是float型(4字节)。

	int a=10;cout<<sizeof(a*1.0f)<<endl;cout<<sizeof(a*1.0)<<endl;/*48*/

        这是常见的在除法中避免精度损失的方法,如下:

int a=2;
int b=5;
cout<<a/b<<" "<<a*1.0/b<<endl;
/*0 0.4*/

        这样看似确实解决了精度,但是这只是保证了过程中的精度问题 ,如果我们把这个double类型的值赋给其它变量,那就又要看这个赋值变量了。

float 与 double 的区别 

        float为32位,double位64位,但这并不代表和整型一样,实际用来计算的位数更少,因为有符号位等。就和我们计算Pi后的小数点一样,小数点后位数越多,精度肯定越高。在一些对精度要求高的地方肯定是用double。但是肯定不能和整数运算相比。

        商业级的有BigDecimal,目前在算法比赛中,如果涉及到浮点数运算,大多数都是可以进行约分的,把分母约掉,要仔细观察题目。如果没有,那就是你没找到正确的方法。被迫用小数运算,就用double,不要用float!!!

        最后可以看一下我写的CSP38第一题,一个80分代码,一个AC代码,大家可以看看有什么区别,问题在哪里?

题目:正态分布(normal)--CSP38

        对于正态分布随机变量 X ∼ N(µ, \sigma ^2)(均值 µ、标准差 σ),查表计算 P (X ≤ n)。具体来说,我们首先需要将 X 转换为标准正态分布 Z:

Z=\frac{X-\mu}{\sigma}

那么 X ≤ n 的概率也就等于 Z ≤ \frac{n-\mu}{\sigma}的概率:

P (X \leq n) = P (Z \leq\frac{n-\mu}{\sigma})

        而对于服从标准正态分布的 Z,其小于等于某值的概率 P (Z ≤ m) 可以通过查表得出。图 1 展示了 m 取值从 0.00 到 1.49 的结果(步长 0.01),其中每列对应 m 的百分位、每行对应 m 的十分位和整数部分。该表可继续向下延伸,这里只展示部分结果。

 图 1: 标准正态分布常用值表

        如图 2 所示, Z ≤ 1 的概率即为阴影部分的面积,查看表中 1.0 对应行、 0.00 对应列即可得到近似结果 0.8413。

图 2: 标准正态分布示意图


        在本题中你需要模拟上述查表的过程,处理 k 个如下查询:对于给定的参数 µ、 σ和 n,计算 P (X ≤ n) 的结果在表中的哪一行、哪一列?

        其中行列下标均从 1 开始:

        • 行: 0.0 对应第 1 行, 0.1 对应第 2 行,依此类推……

        • 列: 0.00, 0.01, · · · , 0.09 依次对应第 1、第 2 到第 10 列。

【输入格式】

从标准输入读入数据。

输入的第一行包含一个正整数 k,表示查询的个数。

接下来输入 k 行,每行包含空格分隔的三个整数 µ、 σ 和 n,表示一个查询。

【输出格式】

输出到标准输出。

每个查询输出一行,包含空格分隔的两个整数 i 和 j,表示查询的结果位于表中第i 行、第 j 列。

【样例输入】

1         4

2         0 1 1

3         2 10 127

4         2 50 227

5         5 100 350

【样例输出】

1         11 1

2         126 1

3         46 1

4         35 6

【样例解释】

        第一个查询等价于计算 P (Z ≤ 1-1 0),如题目描述所示,查看表中 1.0 对应行(第11 行)、 0.00 对应列(第 1 列)即可。

【子任务】

全部的数据满足:

• k ≤ 20;

• 参数 µ、 σ 和 n 均为整数;

• 0 ≤ µ ≤ n ≤ 1000;

• 1 ≤ σ ≤ 100 且标准差 σ 是 100 的因子。

80分代码:

#include<bits/stdc++.h>
using namespace std;int main()
{int n;cin>>n;int a=0,b=0,c=0;float s=0;int x=0,y=0;for(int i=0;i<n;i++){cin>>a>>b>>c;s=((c*1.0-a*1.0)*1.0/b*1.0)*10.0;
//		s=((c-a)/b)*10.0;x=(int)s;s=s*1.0-int(s)*1.0;
//		cout<<s<<endl;s*=10.0;y=(int)s;printf("%d %d\n",++x,++y);}return 0;
}

AC代码:

#include<bits/stdc++.h>using namespace std;int k;int main(){cin >> k;while(k--){int u,sgm,n;cin >> u >> sgm >> n;double ans = 0.00;double ans2=0.00;int ans1 = 0;int ans3 = 0;ans = (double) (n-u)/sgm;ans2 = abs((int)(ans*10)-(ans*10))*10+1;ans = ans*10+1;ans1 = ans;cout << ans1 << " " <<ans2 << endl;}
}

         目前我想的就是float与double问题,最后推测一个正确代码,具体还要等我下次模拟开放提交一下代码试试了:

#include<bits/stdc++.h>
using namespace std;int main(){int u,Sigma,n;int Z;cin>>u>>Sigma>>n;Z=(u-n)*100/Sigma;/*不会用到小数,直接忽略*/cout<<Z/10<<" "<<Z%10;return 0;
}

参考文献

浮点类型计算精度不准确原因及如何规避 - wangsong412 - 博客园

http://www.xdnf.cn/news/12974.html

相关文章:

  • (新)Gateway网关+基于Nacos配置动态路由
  • 【Ftrace专栏】function graph的trace输出格式使用
  • NumPy数组属性
  • 《最短路(Floyd)》题集
  • Qwen3开源最新Embedding模型
  • Cesium快速入门到精通系列教程八:时间系统
  • 【术语扫盲】评估指标Precision、Recall、F1-score、Support是什么含义?
  • 论文解析:一文弄懂Transformer!
  • Visio粘贴Word公式技巧
  • 深究二分查找算法:从普通到进阶
  • AI书签管理工具开发全记录(十六):Sun-Panel接口分析
  • Java中线程的常用方法
  • 6月8日python-AI代码
  • RPG23.应用武器伤害(一):设置武器命中
  • AD学习(2)
  • 深入理解链接与加载:从静态库到动态库的全流程解析
  • OD 算法题 B卷【反转每对括号间的子串】
  • Java设计模式面试题详解
  • 第十二讲 | 二叉搜索树
  • 庖丁解java(一篇文章学java)
  • 风控系统中常用的概念和架构学习
  • golang循环变量捕获问题​​
  • Ⅱ.楔子 -- C♭和 cbc
  • 经典算法:排序链表
  • DQN算法(详细注释版)
  • 开源项目实战学习之YOLO11:12.7 ultralytics-models-transformer.py
  • SpringMVC简介
  • 【GPT模型训练】第一课:安装PyTorch环境
  • PandasAI使用
  • Doris-2:单虚拟机上非docker化安装Doris实验环境