原理:二分
一个小小的整型传实型(int传double)在控制变量数次后终于才让我给找了出来。一个基础又愚蠢的错误
错误代码如下:
#include <iostream>
#include <math.h>
const double PI = 3.141592653589793;
const double EPS = 1e-6;
using namespace std;
double DevidePai(int a[] , int n , int ren , double left , double right);
int Judge (int a[] ,int ren , int n , double D);
int main(){
int n , F , sum = 0;//错误处
scanf("%d%d" , &n , &F);
int a[n];
for(int i = 0;i < n;i++){
scanf("%d" , &a[i]);
sum += a[i]*a[i];
}
printf("%.3lf" , PI*DevidePai(a,n,F+1,0, sum/F+1) );
//错误传递处
return 0;
}
double DevidePai(int a[] , int n , int ren , double left , double right){
double answar = (left+right)/2;
for(; ;){
if(right-left < EPS){
return answar;
}
answar = (left + right)/2;
if( Judge(a,ren,n,answar) ){
left = answar;
}else{
right = answar;
}
}
}
int Judge (int a[] ,int ren , int n , double D){
int flag = 1;
for(int i = 0;i < n;i++){
ren-= (int)(a[i]*a[i]/D);
}
if(ren > 0){flag--;}
return flag;
}
正确代码如下:
#include <iostream>
#include <math.h>
const double PI = 3.141592653589793;
const double EPS = 1e-6;
using namespace std;
double DevidePai(int a[] , int n , int ren , double left , double right);
int Judge (int a[] ,int ren , int n , double D);
int main(){
int n , F ;
double sum = 0;//int 和double传递时会有各种奇奇怪怪的问题
scanf("%d%d" , &n , &F);
int a[n];
for(int i = 0;i < n;i++){
scanf("%d" , &a[i]);
sum += a[i]*a[i];
}
printf("%.3lf" , PI*DevidePai(a,n,F+1,0, sum/F+1) );
return 0;
}
double DevidePai(int a[] , int n , int ren , double left , double right){
double answar = (left+right)/2;
for(; ;){
if(right-left < EPS){
return answar;
}
answar = (left + right)/2;
if( Judge(a,ren,n,answar) ){
left = answar;
}else{
right = answar;
}
}
}
int Judge (int a[] ,int ren , int n , double D){
int flag = 1;
for(int i = 0;i < n;i++){
ren-= (int)(a[i]*a[i]/D);
}
if(ren > 0){flag--;}
return flag;
}
//总结:
1.精确计算和大型数据下函数的return值依然精确不会影响。
2.在精确计算和大型数据下,即使你代码逻辑没错,若传形参时类型不一很可能会发生额外的错误且难以发觉。