Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 数值解不';不要分道扬镳。为什么?_C++_Precision_Numerical Integration - Fatal编程技术网

C++ 数值解不';不要分道扬镳。为什么?

C++ 数值解不';不要分道扬镳。为什么?,c++,precision,numerical-integration,C++,Precision,Numerical Integration,我尝试使用Euler方法来近似一个微分方程: u'=3*(u-t) u(0)=1/3 要解决此问题,应使用浮点精度进行大量步骤的发散。这是由于初始数据的舍入误差造成的。 对我的一些朋友来说,这个密码是不同的,但对我来说不是 编译器是否可能正在提高精度 更新评论: @KillzoneKid nog++-Wall-pedantic main.cpp不打印任何内容 @一些程序员认为实际输出是精确解,而由于浮动误差,输出应该发散。类似于7189而不是10+1/3(精确解) @pac0编译后的输出不起作

我尝试使用Euler方法来近似一个微分方程:

u'=3*(u-t)
u(0)=1/3
要解决此问题,应使用浮点精度进行大量步骤的发散。这是由于初始数据的舍入误差造成的。 对我的一些朋友来说,这个密码是不同的,但对我来说不是

编译器是否可能正在提高精度

更新评论:

@KillzoneKid no
g++-Wall-pedantic main.cpp
不打印任何内容

@一些程序员认为实际输出是精确解,而由于浮动误差,输出应该发散。类似于7189而不是10+1/3(精确解)

@pac0编译后的输出不起作用,因为其他人都在使用非常旧的linux版本(内核2.6),但我将尝试设置编译器选项

现在的趋势是,mac电脑用户(我的朋友)和现代linux用户(me)都会遇到这个问题,而windows或非常旧的linux用户则不会

@1201程序我在XPS15上使用Ubuntu17.10,CLion作为编辑器。 为了简单起见,我使用的是捆绑在操作系统中的g++

#include <iostream>
#include <math.h>
#include <fstream>

using namespace std;
typedef float Real;
Real f(Real t,Real u);
const Real pi=4.0*atan(1.0);

int main() {

    Real u,t,T,tau;


    // print to file
    char n_file[21]={0};
    std::cout << "file name: " << std::endl;
    std::cin >> n_file ;

    ofstream prt(n_file);
    prt.precision(15);
    //

    t=0.0;//start time
    T=10.0;//final time
    u=1.0/3.0;// u(0)
    unsigned long N;
    for(int k=1;k<=20;k++){
        N=(unsigned long)pow(10,k);
        tau=(T-t)/Real(N);
        for(unsigned long n=1;n<=N;n++){
            u+=tau*f(t,u);
            t+=tau;
        }
        prt << "With " << N << " steps, at time " << tau << "result is " <<u<<endl;

        prt << endl << endl << endl;

        u = 1.0/3.0;
        t = 0.0;

    }

//

    return 0;
}


//
Real f(Real t, Real u)
{
    return 3*(u-t);
}
#包括
#包括
#包括
使用名称空间std;
typedef浮点实数;
实f(实t,实u);
常数实pi=4.0*atan(1.0);
int main(){
真u,t,t,tau;
//打印到文件
字符n_文件[21]={0};
std::cout n_文件;
流prt(n_文件);
精密度(15);
//
t=0.0;//开始时间
T=10.0;//最后一次
u=1.0/3.0;//u(0)
无符号长N;

对于(int k=1;k,
u=1.0/3.0+1e-8;
的计算以双精度完成,然后在分配给u时四舍五入到最接近的浮点值。使用Windows和Visual Studio,在从双精度转换为浮点期间,+1e-8会四舍五入,但+1e-7足够大,足以影响浮点结果:

1.0/3.0 + 1e-8 == 1.0/3.0 == 32 bit hex integer 0x3eaaaaab
                          ~= 0.33333334

1.0/3.0 + 1e-7 ==            32 bit hex integer 0x3eaaaaae
                          ~= 0.33333343

环境之间的差异可能是浮点控制字的舍入设置问题,也可能是硬件实现问题


我将代码更改为使用2次方的步长计数(在本例中为8次方),并将最大步长限制为对应于浮点尾数部分的有效位数。这消除了发散,部分原因是u的初始值略大于1/3,而t和tau是精确的(因为步长计数是2的幂),部分原因是乘以tau减少的误差大于重复加法增加的误差。将u初始化为1/3-1e-7,和在64步处发散,变成-5770,但对于8步,它是10.30,对于>=512步,它是10.333333

#include <iomanip>
#include <iostream>
#include <math.h>
#include <fstream>

using namespace std;
typedef float Real;
Real f(Real t,Real u);

int main() {
    Real u,t,T,tau;

    // print to file
    char n_file[21]={0};
    std::cout << "file name: " << std::endl;
    std::cin >> n_file ;

    ofstream prt(n_file);
    prt.precision(15);

    T=10.0;    //final time
    unsigned long N = 1;
    for(int k=1;k<=7;k++){
        N *= 8;                 // # steps is power of 2
        u = (Real)(1.0/3.0);
        t = 0.0;
        tau=T/Real(N);
        for(unsigned long n=1;n<=N;n++){
            u+=tau*f(t,u);
            t+=tau;
        }
        prt << "With " << setw(8) << N << " steps result is " << u <<endl;
    }

    return 0;
}

Real f(Real t, Real u)
{
    return 3*(u-t);
}
#包括
#包括
#包括
#包括
使用名称空间std;
typedef浮点实数;
实f(实t,实u);
int main(){
真u,t,t,tau;
//打印到文件
字符n_文件[21]={0};
std::cout n_文件;
流prt(n_文件);
精密度(15);
T=10.0;//最后一次
无符号长N=1;

对于(int k=1;kDo),您会收到任何
double
to
float
转换警告?对于某些输入(您需要告诉我们)预期和实际输出是什么?您是否尝试过?“对于我的一些朋友,此代码发散”,如果你在你的机器上编译并给他们可执行文件,是否也有区别?你使用的是哪种编译器/版本?与你的朋友使用的编译器/版本相同吗?不清楚为什么你确定这应该“不同”。抱歉,这是一个测试。原始代码没有。如果您在没有测试的情况下运行代码,最终结果是什么?10.333333…?@Mascarpone-使用Win 7 Pro 64位Visual Studio 2015,它会出现分歧。将步数更改为2的幂可以解决此问题。此外,10^20不适合64位整数,更不用说32位整数,f面包的有效期只有7位数。我更新了我的答案。