所以,伙计们。我对Java(以及其他任何编程语言)都很陌生,而且我在处理列表时遇到了一些麻烦。我已经编写了这段代码,以便集成一个函数,给定低级和高级限制,以及调步。虽然,我注意到,对于不同于1的调步,列表(list_x)会搞砸,并且值会直接到达它的末尾。 以下是完整的代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Integrate {
static List<Double> fillx(double ini,double end, double pace) { //Fills the x column
List<Double> list_x = new ArrayList<Double>();
for(double i = ini; i <= (end+0.1*pace); i += pace) {
int i2 = (int) ((i-ini)/pace);
list_x.add(i2, i);
}
System.out.println(list_x);
return list_x;
}
static List<List<Double>> filly(List<Double> listx){ //Fills the y column
List<List<Double>> listxy= new ArrayList<List<Double>>();
for(int i = 0; i < listx.size();i++) {
List<Double> pair = new ArrayList<Double>();
pair.add(0,listx.get(i));
pair.add(1,function(listx.get(i)));
listxy.add(i,pair);
System.out.println(pair);
}
return listxy;
}
static double function(double x) { //Defines the function to be integrated
return x;
}
static double integrate(List<List<Double>> listxy) { //Integrates following trapezoidal forms
double area = 0;
for(int i=0; (i+1) < listxy.size();i++) {
area += 0.5*(listxy.get(i+1).get(0)-listxy.get(i).get(0))* (listxy.get(i+1).get(1)+listxy.get(i).get(1));
System.out.println(listxy.get(i+1).get(0)+" "+listxy.get(i).get(0)+" "+listxy.get(i+1).get(1)+" "+listxy.get(i).get(1));
}
return area;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
double ini = scan.nextDouble(); //Reads the inferior limit
double end = scan.nextDouble(); //Reads the superior limit
double pace = scan.nextDouble(); //Reads the pace (partial to be summed).
if (((end-ini) % pace) < pace) {
System.out.println(integrate(filly(fillx(ini,end,pace))));}
else
System.out.println("Must review pace");
}
}
我得到了这些结果(值为ini = 0,end = 1,pace = 1E-1
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999, 0.5]
如果你还有其他任何评论,我会很高兴的。由于我自己学习,所有的帮助都是受欢迎的。
答案 0 :(得分:0)
构造list_x时,会发生以下情况:
adding 0.0 at index 0 [0.0]
...
adding 0.5 at index 5 [0,0, 0.1,... 0.5]
adding 0.6 at index 5 Bang: [0,0, 0.1,... 0.6, 0.5]
adding 0.7 at index 6 [0,0, 0.1,... 0.6, 0.7, 0.5]
你看到这是如何将0.5推到最后。
你正在做所谓的“过度工程”:害怕做得不够,做得太多。
// The List is perfectly capable of appending at the end, which is exactly what you want:
for(double i = ini; i <= (end+0.1*pace); i += pace) {
list_x.add(i);
}
还有很多需要说的。我将添加一些评论 - 坚持下去。
脚注1 双重算术
int i2 = (int) ((i-ini)/pace);
此类计算存在风险。除法可能导致一个值或略高于整数,然后转换为int截断并产生您期望的值。但是,它可能会稍微返回一个双倍(请参见那些0.x999999999999999),然后截断结果会比您预期的少一个。
int i2 = (int)Math.round((i-ini)/pace);
脚注2 计算一系列双打
不是将double重复添加到另一个double,而是直接计算。 (我还添加了ini,以获得正确的横坐标值。)
int n = (int)Math.round((end - ini)/pace) + 1;
for(int i = 0; i < n; ++i) {
list_x.add(ini + i*pace);
}
Footnode 3 使用适当的课程
两个列表不是存储一对坐标的好方法。可以定义一个简单的类Point:
public class Point {
private double x;
private double y;
Point( double x, double y ){
this.x = x;
this.y = y;
}
public double getX(){
return x;
}
public double getY(){
return y;
}
public String toString(){
return "<" + x + "," + y + ">";
}
}
现在,x-y组合可以像这样计算:
static List<Point> fillp(List<Double> listx){
List<Point> listp = new ArrayList<>();
for(int i = 0; i < listx.size(); i++) {
Point p = new Point( listx.get(i), function(listx.get(i)) );
listp.add( p );
}
return listp;
}
脚注4 为什么列出所有这些?
无需存储可轻松计算的值或仅计算一次的值。只需动态计算它们即可。这简化了您的代码:
public class Trapez {
static double function(double x) { //Defines the function to be integrated
return x;
}
static double trapezoidalRule( double a, double b, double h ){
int n = (int)Math.round((b - a)/h) + 1;
double area = 0;
double y = function( a );
for( int i = 1; i < n; i++ ){
double y1 = function( a + h*i );
area += 0.5*h*(y + y1);
y = y1;
}
return area;
}
public static void main(String[] args) {
System.out.println( trapezoidalRule( 0, 1, 0.1 ) );
}
}
结论传递函数的更好方法是什么?
Java 8具有函数形式(lambdas)。在简单的情况下,它们易于使用,我在删除方法function
时结束了我的讨论。 (我使用f(x)= 2x使函数定义与参数不同。)
import java.util.function.Function;
public class Trapez {
static double trapezoidalRule( Function<Double,Double> f, double a, double b, double h ){
int n = (int)Math.round((b - a)/h) + 1;
double area = 0;
double y = f.apply( a );
for( int i = 1; i < n; i++ ){
double y1 = f.apply( a + h*i );
area += 0.5*h*(y + y1);
y = y1;
}
return area;
}
public static void main(String[] args) {
System.out.println( trapezoidalRule( x -> 2*x, 0, 1, 0.1 ) );
}
}