double 类型避免大数误差?
  • 板块学术版
  • 楼主Adolfo_North
  • 当前回复0
  • 已保存回复0
  • 发布时间2025/1/26 22:23
  • 上次更新2025/1/27 12:54:10
查看原帖
double 类型避免大数误差?
616964
Adolfo_North楼主2025/1/26 22:23

题目描述

条件概率可以通过骰子问题来阐释。在一对普通的6面骰子中,已知至少有一个骰子显示为6,那么两个骰子点数之和为12的概率是多少呢?这与下面这个问题是等价的:掷一对骰子,直到至少有一个骰子显示为6,那么最终掷出的结果两个骰子都为6的概率是多少。令人惊讶的答案是1/11,因为在36种等可能的掷骰子结果中,有11种结果至少有一个6,而这11种结果中只有1种是两个骰子都为6。

我们的目标是解决这个问题的一个广义版本。在这个版本中,我们掷 nDice 个相同的骰子,每个骰子的面标有1、2、……、maxSide。已知至少有一个骰子显示的值为 v,我们想知道骰子点数之和大于或等于 theSum 的概率。创建一个名为 Conditional 的类,其中包含一个方法 probability,该方法接收 nDice、maxSide、v 和 theSum 作为参数,并返回所需的条件概率。

输入格式

int nDice:骰子的数量

int maxSide:骰子的最大面数

int v:特定值

int theSum:目标点数和

输出格式

double:表示所求的条件概率。

数据:

in:
50
50
1
1234
out:
0.6065038966315277

这是错误代码,由输出为负数可知,开启全局 long long 后 sum 与 all,任然炸了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=60;
double f[N][N*N][2];
int dc,msi,v,ths;
signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>dc>>msi>>v>>ths;
	f[0][0][0]=1;
	for(int i=1;i<=dc;i++){
		for(int j=0;j<=(i-1)*msi;j++){
			for(int k=1;k<=msi;k++){
				if(k==v) f[i][j+k][1]+=f[i-1][j][0]+f[i-1][j][1];
				else {
					f[i][j+k][1]+=f[i-1][j][1];
					f[i][j+k][0]+=f[i-1][j][0];
				}
			}
		}
	}
	int sum=0,all=0;
	for(int i=0;i<=msi*dc;i++){
//		cout<<f[dc][i][1]<<'\n';
		if(i>=ths) sum+=f[dc][i][1];
		all+=f[dc][i][1];
//		cout<<sum<<' '<<all<<'\n';
	}
//	cout<<sum<<' '<<all<<'\n';
	printf("%.20lf",(sum*1.0)/(all*1.0));
	return 0;
}

但是更换为 double 后,竟然神奇的好了:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=60;
double f[N][N*N][2];
int dc,msi,v,ths;
signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>dc>>msi>>v>>ths;
	f[0][0][0]=1;
	for(int i=1;i<=dc;i++){
		for(int j=0;j<=(i-1)*msi;j++){
			for(int k=1;k<=msi;k++){
				if(k==v) f[i][j+k][1]+=f[i-1][j][0]+f[i-1][j][1];
				else {
					f[i][j+k][1]+=f[i-1][j][1];
					f[i][j+k][0]+=f[i-1][j][0];
				}
			}
		}
	}
	double sum=0,all=0;
	for(int i=0;i<=msi*dc;i++){
//		cout<<f[dc][i][1]<<'\n';
		if(i>=ths) sum+=f[dc][i][1];
		all+=f[dc][i][1];
//		cout<<sum<<' '<<all<<'\n';
	}
//	cout<<sum<<' '<<all<<'\n';
	printf("%.20lf",(sum*1.0)/(all*1.0));
	return 0;
}

double 存大数精度这么高的吗?

2025/1/26 22:23
加载中...