小弟最近学习使用C++编程,在编程过程中子函数里遇到一个数量级为e-19的小数,方程里的参数数值类型都为long double,方程里所有参数的值都是正确的,但是方程无法计算初正确结果,有哪位大神可以指点一下让代码运行出正确结果,代码和运行结果如下
#include <iostream>
#include "math.h"
int main(void)
{
long double z0, ax, ay, y0 ,delta_i, delta_e, y1, y2,ro,ri,d;
ax = 3.274562789467620e-4;
ay = 1.071061271913181e-3;
z0 = 9.355885717696390e-5;
y0 = 3.060172456885287e-4;
ri = 8.800000608712444e-3;
ro = 8.320000090002999e-3;
d = 1.600000075995922e-2;
y1 = 0;
y2 = 0;
delta_e = sqrtl((z0*1e8 - y1 * 1e8)*(z0*1e8 - y1* 1e8) + (y0*1e8 + y2 * 1e8)*(y0*1e8 + y2 * 1e8));
delta_e = delta_e / 1e8 - (ro - 0.5*d);
delta_i = sqrtl((ax *1e8 - z0 *1e8 + y1 * 1e8)*(ax *1e8 - z0 *1e8 + y1 * 1e8) + (ay*1e8 - y0 *1e8 - y2 * 1e8)*(ay*1e8 - y0*1e8 - y2 * 1e8));
delta_i = delta_i / 1e8 - (ri - d *0.5);
}
为什么delta_e的结果是正确的,而delta_i的结果却是0?
而且将delta_e计算中的参数与别的数量级的数比如1e10 而不是1e8相乘 的话那delta_e的结果也不正确。
希望能够实现结果
附正确结果:delta_e=5.421010862427522e-20
delta_i=1.084202172485504e-19
首先还是精度要求太高了,long double只能保证17~18位的存储精度,超出部分知识随机赋值,显示的结果并不是真正的数值,可以采用字符串表示数值,达到更高的精度要求
精度要求太高了,超越double的承受范围了。
doubule类型是64位的浮点型。 也就是说64位为中有一些可以用来表示小数。做多只有52位表示小数部分。
那么doubule的小数部分所能承受的数字范围就是0到2的52次方这么多个数。2的2的52次方是4,503,599,627,370,496,也就是大概4.5x10的15次方。
你这个10的-19次方显然已经越界了,所以我不确认这个的delta_e 是不是也是精确的。再次计算后,计算机就认为太小了,直接给你0显示了
这个需要编写代码去模拟这种高精度的大数运算。
首先实现大数的四则运算(这个网上有)
然后用牛顿迭代法开平方。参考这个 https://blog.csdn.net/YGLeeeon/article/details/101028350
如数上两位所述,你的程序没问题,只是64位浮点运算只能保证每一次运算的前15位(十进制)正确,开方也是这样,当两个开方后的数再进行减法运算时,
如果前15位有效数字相同,则结果就只是0了。解决方法是要自己写精度的浮点计算程序.
确实是你的精度太高了,建议可以先将这些变量扩大若干倍,然后对最后的结果在进行相应的缩小若干倍即可
duoble 类型:8个字节,64位bites正负1.7乘以10的308次方,精度:小数点后15位,但是你需要小数点后20位的精度,明显超过了,只要你的整数部分
不超过1.7乘以10的303次方,那么你就可以直接将所有的数据乘以10的5次方来计算,最后得到的结果除以10的五次方,这样最简单