69,371
社区成员
发帖
与我相关
我的任务
分享
// 推理
// 0.038f + 0.46e <= 2.56*10^9 此为直线,且其一面有效
// q = f^0.4 * E^0.6 此为曲线
// 如图,当Q越大时,曲线向直线无效方向移动,故最大Q时,当为曲线与直线的相切点
double LIM_ = 2.56e9;
double getlim(double _f, double _e)
{
return 0.038* _f + 0.46*_e;
}
double getf(double _e)
{
return (LIM_ - 0.46*_e) / 0.038;
}
double gete(double _f)
{
return (LIM_ - 0.038*_f) / 0.46;
}
double getq(double _f, double _e)
{
return pow(_f, 0.4) * pow(_e, 0.6);
}
// 此处采用 log2快速逼近
void feq()
{
double e = 0, f=0, lim, q, lastq = -1;
double d = 1;
int n = 0, m = 0;
do
{
n++;
e = gete(f+d);
q = getq(f+d, e);
if (!d) // double最小极限为0
{
m++;
// 如果此点处q是最大,
// 1: 则此点为曲线直线唯一相交点,即为相切点
// 2: 此点两侧任意点的q值必比原q小
// 3: 如果任意一侧q值比原值大,那么此点为相交点,不是切点
double PRI = 1e-4; // 检测精度,太大无效,太小则double精度有限
double fc = f + PRI;
double ec = gete(fc);
double qc = getq(fc, ec);
if (qc > q)
{
d = PRI;
continue;
}
fc = f - PRI;
ec = gete(fc);
qc = getq(fc, ec);
if (qc > q)
{
d = -PRI;
continue;
}
break;
}
if (q > lastq)
{
f += d;
d *= 2;
lastq = q;
}
else
d /= 2;
} while (1);
printf("\n迭代次数:%d, %d, ", n, m);
e = gete(f);
lim = getlim(f, e);
q = getq(f, e);;
printf("\n正解:%e, %e, %e,%e", f, e, lim, q);
double fe = f / e;
double feq = LIM_ /( 0.038 *fe + 0.46) * pow(fe, 04);
f = 3.339e9;
e = 2.65e10;
lim = getlim(f, e);
q = getq(f, e);;
printf("\n原解:%e, %e, %e,%e", f, e, lim, q);
}
迭代次数:2305, 2,
正解:2.688306e+010, 3.344443e+009, 2.560000e+009,7.698139e+009
原解:3.339000e+009, 2.650000e+010, 1.231688e+010,1.157162e+010
注意:原解有误, f 与e 值大误,Q值小误