????????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(μ, )(均值 μ、標準差 σ),查表計算 P (X ≤ n)。具體來說,我們首先需要將 X 轉換為標準正態分布 Z:
那么 X ≤ n 的概率也就等于 Z ≤ 的概率:
????????而對于服從標準正態分布的 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 - 博客園