【问题标题】:My value keeps showing up as NaN我的值一直显示为 NaN
【发布时间】:2014-02-17 12:36:00
【问题描述】:

本质上,我的 delta 值给我带来了一些麻烦,当我将所有变量打印到控制台窗口时,一切都是正确的,除了 delta,它的值一直显示为 NaN。我无法为我的生活找出原因。我是一所大学的 CIS 初级学生,这真的让我很头疼。

import java.util.Scanner;


public class ReimannSumCalculator {
    static double a,b,c,start,end;
    static double partitions;
    static double delta=end - start / partitions;

    private static double Quadratic(double a,double b,double c,double x) {
        double Quadratic = a*x*x + b*x + c;
        return Quadratic;
    }


    public static void leftReiman(double a,double b,double c,double delta,double start,double end) {
        double leftReiman = 0;

        for(double x = start; x<end; x+=delta) {
            leftReiman = delta * Quadratic(a,b,c,x) + leftReiman;
        }

        System.out.println("Your left Reiman sum is " + leftReiman);
    }

    public static void rightReiman(double a,double b,double c,double delta,double start,double end) {
        double rightReiman = 0;

        for(double x = start+delta; x<=end; x+=delta) {
            rightReiman = delta* Quadratic(a,b,c,x) + rightReiman;
        }

        System.out.println("Your right Reiman sum is " + rightReiman);
    }

    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);

        System.out.println("Please enter some values for a b and c.");

        a = keyboard.nextDouble();
        b = keyboard.nextDouble();
        c = keyboard.nextDouble();

        System.out.println("Please enter a start and end point.");

        start = keyboard.nextDouble();
        end = keyboard.nextDouble();

        System.out.println("Now enter the amount of partitions.");

        partitions = keyboard.nextInt();

        leftReiman(a,b,c,start,end,delta);
        rightReiman(a,b,c,start,end,delta);

        System.out.println("The delta is: " + delta);
        System.out.println("The amount of partitions are: " + partitions);
        System.out.println("a is: "+ a);
        System.out.println("b is: "+ b);
        System.out.println("c is: " + c);
        System.out.println("The start is: " + start);
        System.out.println("The end is: " + end);
    }
}

【问题讨论】:

  • 如果您要发布一些代码,请花一些时间将其格式化为可读形式。请。这一次我为你做到了。

标签: java variables nan


【解决方案1】:

在初始化这些变量之一之前,您正在执行start / partitions。

所以你实际上是在计算 0.0/0.0,它等于 NaN。

【讨论】:

    【解决方案2】:

    Java 并不擅长。它不会自动计算符号表达式的运算顺序,也不会在输入更改时重新计算表达式。

    获得正确的操作顺序以及在输入过时时重新计算值的负担由程序员承担。

    static double a,b,c,start,end;
    
    static double partitions;
    
    static double delta=end - start / partitions;
    

    等价于

    static double a,b,c,start = 0.0d, end = 0.0d;
    
    static double partitions = 0.0d;
    
    static double delta=end - start / partitions;
    

    因为所有字段的类型都取零值,相当于

    static double a,b,c,start = 0.0d, end = 0.0d;
    
    static double partitions = 0.0d;
    
    static double delta=0.0d - 0.0d / 0.0d;   // division by zero -> NaN
    

    因为字段是按照它们的声明顺序初始化的。

    然后您无法在main 的主体中重新计算delta,因此您最终将NaN 的delta 传递给leftReimann 和rightReimann。


    使用整数循环来确保处理正确数量的分区而不是将double x 与双边界进行比较可能是有意义的。浮点运算是有损的,因此在循环条件中检查 doubles 时可能会遇到边界条件。

    public static double leftReimann(double a,double b,double c,int partitions,double start,double end) {
        assert partitions > 0;
    
        double leftReimann = 0;
    
        double delta = (end - start) / partitions;
    
        for(int i = 0; i < partitions; ++i) {
            double x = start + delta * i;
            leftReimann += delta * Quadratic(a,b,c,x);
        }
    
        System.out.println("Your left Reimann sum is " + leftReimann);
        return leftReimann;
    }
    
    public static double rightReimann(double a,double b,double c,int partitions,double start,double end) {
        assert partitions > 0;
    
        double rightReimann = 0;
    
        double delta = (start - end) / partitions;  // negative
    
        for(int i = 0; i < partitions; ++i) {
            double x = end + delta * i;
            rightReimann += delta * Quadratic(a,b,c,x);
        }
    
        System.out.println("Your right Reimann sum is " + rightReimann);
        return rightReimann;
    }
    

    【讨论】:

    • 感谢您提供的非常好的答案。这就说得通了。我已经通过在我的 main 方法中重新计算它来修复我的 delta 值,但是,您对为什么我的 Right Reimann sum 方法和 Left Reimann sum 方法都返回零有任何见解吗?
    • @JustinTaylor,当你重新计算它时,partitions 是什么?如果分区很小,那么您可能会遇到边界问题。浮点值上的&lt;= 是狡猾的,因此如果您将分区视为int 并循环遍历分区数,您的 reimann 可能会更可靠。
    • @JustinTaylor,请参阅我修改后的评论重新 int 循环。
    • @JustinTaylor,end - start / partitions 也等同于 end - (start / partitions),因为除法的运算符优先级高于减法。它与(end - start) / partitions 不同,这可能是您想要的。
    【解决方案3】:

    有两个选择,要么让 delta 成为一个函数

    private double getDelta() { return (end - start) / partitions;
    

    或者,您可以在设置结束、开始或分区后重新计算增量。 (在这种情况下,在调用 Reiman 函数之前,您应该说:

    delta = (end - start) / partitions;
    

    所以它使用 end、start 和 partitions 的新值。

    正如其他人所说,在初始化 delta 时,分区为零,因此除以零是 NaN。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-13
      • 1970-01-01
      • 2016-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-07
      相关资源
      最近更新 更多