java 中的欧拉方法
Euler's Method in java
我已经编写了一个欧拉方法代码来找到 x(10) 的近似值并将其与 separable ODE 中给出的精确解给出的 x(10) 的值进行比较。但是,我的代码为 x(10) 显示了一个混沌数。你能确定一个主要错误吗?
谢谢。
//@(#)euler.java
//This method attempts to find solutions to dx/dt = (e^t)(sin(x)) via
//Euler's iterative method and find an approximate value for x(10)
import java.text.DecimalFormat;
public class euler
{
public static void main(String[] Leonhard)
{
DecimalFormat df = new DecimalFormat("#.0000");
double h = (1.0/3.0); // h is the step-size
double t_0 = 0; // initial condition
double x_0 = .3; // initial condition
double x_f = 10; // I want to find x(10) using this method and compare it to an exact value of x(10)
double[] t_k;
t_k = new double[ (int)( ( x_f - x_0 ) / h ) + 1 ] ; // this two arrays hold the values of x_k and t_k
double[] x_k;
x_k = new double[ (int)( ( x_f - x_0 ) / h ) + 1 ] ;
int i; // the counter
System.out.println( "k\t t_k\t x_k" ); // table header
for ( i = 0; k < (int)( ( x_f - x_0 ) / h ) + 1; i++ )
{
if ( i == 0 ) // this if statement handles the initial conditions
{
t_k[i] = t_0;
x_k[i] = x_0;
}
else if ( i > 0 )
{
t_k[i] += i*h;
x_k[i] = x_k[i-1] + h*( Math.exp(t_k[i-1]))*(Math.sin(x_k[i-1]) );
}
System.out.println( k + " " + df.format(t_k[i]) + " " + df.format( x_k[i]) );
}
}
}
您的代码似乎有效。问题在于欧拉方法是一种相当简单的微分方程近似积分方法。正如您所注意到的,它的准确性在很大程度上取决于您使用的步长。
我 运行 你的代码并与相同算法的另一个实现进行了比较。结果在近似值起作用的范围内重叠,并且超出了很长一段时间。它们只有在方法严重崩溃时才会有所不同:
需要注意的是,欧拉方法对于这个特定的微分方程,对于您希望达到的点,效果不是很好。 1/3
的步长太大而无法开始,但即使您选择更小的步长,例如 1/10000
,该方法往往会在达到 t=10
之前崩溃。 exp(t)sin(x)
之类的东西很难处理。实解变得平坦,接近 pi
,因此 sin(x)
应该趋于零,从而使导数也为零。但是,exp(t)
爆炸了,因此导数在数值上不稳定。
我已经编写了一个欧拉方法代码来找到 x(10) 的近似值并将其与 separable ODE 中给出的精确解给出的 x(10) 的值进行比较。但是,我的代码为 x(10) 显示了一个混沌数。你能确定一个主要错误吗?
谢谢。
//@(#)euler.java
//This method attempts to find solutions to dx/dt = (e^t)(sin(x)) via
//Euler's iterative method and find an approximate value for x(10)
import java.text.DecimalFormat;
public class euler
{
public static void main(String[] Leonhard)
{
DecimalFormat df = new DecimalFormat("#.0000");
double h = (1.0/3.0); // h is the step-size
double t_0 = 0; // initial condition
double x_0 = .3; // initial condition
double x_f = 10; // I want to find x(10) using this method and compare it to an exact value of x(10)
double[] t_k;
t_k = new double[ (int)( ( x_f - x_0 ) / h ) + 1 ] ; // this two arrays hold the values of x_k and t_k
double[] x_k;
x_k = new double[ (int)( ( x_f - x_0 ) / h ) + 1 ] ;
int i; // the counter
System.out.println( "k\t t_k\t x_k" ); // table header
for ( i = 0; k < (int)( ( x_f - x_0 ) / h ) + 1; i++ )
{
if ( i == 0 ) // this if statement handles the initial conditions
{
t_k[i] = t_0;
x_k[i] = x_0;
}
else if ( i > 0 )
{
t_k[i] += i*h;
x_k[i] = x_k[i-1] + h*( Math.exp(t_k[i-1]))*(Math.sin(x_k[i-1]) );
}
System.out.println( k + " " + df.format(t_k[i]) + " " + df.format( x_k[i]) );
}
}
}
您的代码似乎有效。问题在于欧拉方法是一种相当简单的微分方程近似积分方法。正如您所注意到的,它的准确性在很大程度上取决于您使用的步长。
我 运行 你的代码并与相同算法的另一个实现进行了比较。结果在近似值起作用的范围内重叠,并且超出了很长一段时间。它们只有在方法严重崩溃时才会有所不同:
需要注意的是,欧拉方法对于这个特定的微分方程,对于您希望达到的点,效果不是很好。 1/3
的步长太大而无法开始,但即使您选择更小的步长,例如 1/10000
,该方法往往会在达到 t=10
之前崩溃。 exp(t)sin(x)
之类的东西很难处理。实解变得平坦,接近 pi
,因此 sin(x)
应该趋于零,从而使导数也为零。但是,exp(t)
爆炸了,因此导数在数值上不稳定。