Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.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
Java 什么会导致浮点数在没有算术更改的情况下突然关闭1位_Java_Floating Point_Floating Point Precision - Fatal编程技术网

Java 什么会导致浮点数在没有算术更改的情况下突然关闭1位

Java 什么会导致浮点数在没有算术更改的情况下突然关闭1位,java,floating-point,floating-point-precision,Java,Floating Point,Floating Point Precision,在做了一个不修改任何算法的较大重构更改时,我设法以某种方式更改了程序的输出(基于代理的模拟系统)。现在,输出中的各种数字都减少了很小的数量。检查表明,这些数字在其最低有效位中偏离了1位 例如,24.198110084326416将变成24.19811008432642。每个数字的浮点表示形式为: 24.198110084326416 = 0 10000000011 1000001100101011011101010111101011010011000010010100 24.1981100843

在做了一个不修改任何算法的较大重构更改时,我设法以某种方式更改了程序的输出(基于代理的模拟系统)。现在,输出中的各种数字都减少了很小的数量。检查表明,这些数字在其最低有效位中偏离了1位

例如,24.198110084326416将变成24.19811008432642。每个数字的浮点表示形式为:

24.198110084326416 = 0 10000000011 1000001100101011011101010111101011010011000010010100
24.19811008432642  = 0 10000000011 1000001100101011011101010111101011010011000010010101
我们注意到最低有效位是不同的

我的问题是,在我没有修改任何类型的算术的情况下,我如何能够引入这种变化?更改涉及通过删除继承来简化对象(其超类中包含了不适用于该类的方法)

我注意到,输出(在模拟的每个刻度上显示某些变量的值)有时会关闭,然后对于另一个刻度,数字与预期一样,只是在接下来的刻度上再次关闭(例如,在一个代理上,其值在滴答声57-83上显示此问题,但与滴答声84和85的预期一样,只在滴答声86上再次关闭)

我知道我们不应该直接比较浮点数。当仅仅将输出文件与预期输出进行比较的集成测试失败时,就会注意到这些错误。我可以(也许也应该)修复解析文件的测试,并将解析的double与一些epsilon进行比较,但是我仍然很好奇为什么会引入这个问题

编辑:

导致问题的最小变化差异:

diff --git a/src/main/java/modelClasses/GridSquare.java b/src/main/java/modelClasses/GridSquare.java
index 4c10760..80276bd 100644
--- a/src/main/java/modelClasses/GridSquare.java
+++ b/src/main/java/modelClasses/GridSquare.java
@@ -63,7 +63,7 @@ public class GridSquare extends VariableLevel
    public void addHousehold(Household hh)
    {
        assert household == null;
-       subAgents.add(hh);
+       neighborhood.getHouseholdList().add(hh);
        household = hh;
    }

@@ -73,7 +73,7 @@ public class GridSquare extends VariableLevel
    public void removeHousehold()
    {
        assert household != null;
-       subAgents.remove(household);
+       neighborhood.getHouseholdList().remove(household);
        household = null;
    }

diff --git a/src/main/java/modelClasses/Neighborhood.java b/src/main/java/modelClasses/Neighborhood.java
index 834a321..8470035 100644
--- a/src/main/java/modelClasses/Neighborhood.java
+++ b/src/main/java/modelClasses/Neighborhood.java
@@ -166,9 +166,14 @@ public class Neighborhood extends VariableLevel
    World world;

    /**
+    * List of all grid squares within the neighborhood.
+    */
+   ArrayList<VariableLevel> gridSquareList = new ArrayList<>();
+
+   /**
     * A list of empty grid squares within the neighborhood
     */
-   ArrayList<GridSquare> emptyGridSquareList;
+   ArrayList<GridSquare> emptyGridSquareList = new ArrayList<>();

    /**
     * The neighborhood's grid square bounds
@@ -836,7 +841,7 @@ public class Neighborhood extends VariableLevel
     */
    public GridSquare getGridSquare(int i)
    {
-       return (GridSquare) (subAgents.get(i));
+       return (GridSquare) gridSquareList.get(i);
    }

    /**
@@ -865,7 +870,7 @@ public class Neighborhood extends VariableLevel
    @Override
    public ArrayList<VariableLevel> getGridSquareList()
    {
-       return subAgents;
+       return gridSquareList;
    }

    /**
@@ -874,12 +879,7 @@ public class Neighborhood extends VariableLevel
    @Override
    public ArrayList<VariableLevel> getHouseholdList()
    {
-       ArrayList<VariableLevel> list = new ArrayList<VariableLevel>();
-       for (int i = 0; i < subAgents.size(); i++)
-       {
-           list.addAll(subAgents.get(i).getHouseholdList());
-       }
-       return list;
+       return subAgents;
    }
diff--git a/src/main/java/modelClasses/GridSquare.java b/src/main/java/modelClasses/GridSquare.java
索引4c10760..80276bd 100644
---a/src/main/java/modelClasses/GridSquare.java
+++b/src/main/java/modelClasses/GridSquare.java
@@-63,7+63,7@@公共类GridSquare扩展了VariableLevel
公共住户(住户hh)
{
断言住户==null;
-子代理添加(hh);
+getHouseholdList().add(hh);
住户=hh;
}
@@-73,7+73,7@@公共类GridSquare扩展了VariableLevel
公屋住户()
{
断言家庭!=null;
-子代理。移除(家用);
+getHouseholdList().remove(householdlist);
住户=零;
}
diff——git a/src/main/java/modelClasses/Neighborhood.java b/src/main/java/modelClasses/Neighborhood.java
索引834a321..8470035 100644
---a/src/main/java/modelClasses/Neighborhood.java
+++b/src/main/java/modelClasses/Neighborhood.java
@@-166,9+166,14@@公共类邻域扩展VariableLevel
世界;
/**
+*社区内所有网格正方形的列表。
+    */
+ArrayList gridSquareList=新的ArrayList();
+
+   /**
*邻域内的空网格正方形列表
*/
-ArrayList emptyGridSquareList;
+ArrayList emptyGridSquareList=新建ArrayList();
/**
*邻域的方格边界
@@-836,7+841,7@@公共类邻域扩展VariableLevel
*/
公共GridSquare getGridSquare(int i)
{
-返回(GridSquare)(子代理获取(i));
+return(GridSquare)gridsquarlist.get(i);
}
/**
@@-865,7+870,7@@公共类邻域扩展可变级别
@凌驾
公共ArrayList getGridSquareList()
{
-返回子代理;
+返回列表;
}
/**
@@-874,12+879,7@@公共类邻域扩展VariableLevel
@凌驾
公共阵列列表getHouseholdList()
{
-ArrayList=新建ArrayList();
-对于(int i=0;i
不幸的是,我无法创建一个小的、可编译的示例,因为我无法在程序之外复制这种行为,也无法将这个非常大的、纠缠不清的程序缩减到一定的大小

至于要做什么样的浮点运算,没有什么特别令人兴奋的。大量的加法、乘法、自然对数和幂(几乎总是以e为底).后两个是用标准库完成的。随机数在整个程序中使用,并随所使用的框架(Repast)一起生成

大多数数字都在1e-3到1e5之间。几乎没有非常大或非常小的数字。很多地方都使用无穷大和NaN


作为一个基于代理的模拟系统,许多公式被重复应用于模拟出现。评估顺序非常重要(因为许多变量取决于首先评估的其他变量——例如,要计算BMI,我们需要首先计算饮食和心脏状态).变量的先前值在许多计算中也非常重要(因此,这个问题可以在程序早期的某个地方引入,并贯穿整个程序的其余部分).

如果没有精确的源代码来重现问题,显然不可能找出问题所在。但您的差异表明,您改变了列表的处理方式。您还提到,许多简单的数学运算,例如加法,都发生在您的应用程序中。因此,我猜想,通过更改列表,您可以改变列表的顺序ch stuff得到处理,这可能足以改变舍入错误


是的,任何东西都不应该依赖于浮点变量的最低有效位,因此测试应该需要epsilons。

由于strictfp已被消除,我将提供一个想法

某些版本的Repast存在错误,某些随机数生成错误*

即使将随机种子设置为相同的值,ArrayList也是在代码中的不同点创建和使用的
(A + B) + C ≠ A + (B + C)
B < (A * epsilon)
A + B = A