这是我遇到的问题。我有一个CSV文件,我正在阅读4381个小十进制数,大多在-5到5之间。它们的例子是0.00000822, -0.20929117, -2.204, 4.88490078
。
在我用Java编写的程序中,我正在读取CSV文件并将所有4381个数字加在一起以获得总和。但是,我得到的总和甚至没有接近正确的数字。如果我使用=SUM(C:C)
在Excel中将数字列一起添加,我会得到10.77918727
。如果我在程序中将它们添加到一起,我会得到-933.39114459
。如您所见,这些数字甚至都不是很近。我不知道Excel中的值是否正确,但我知道数据没有-933是正确的。
问题是,如果我使用另一个CSV文件中较小的一组数字,数字会正确加起来,所以我确信我的程序正确地添加了。无论如何,我已经放置了我用来在下面添加数字的代码。
因为数字与较小的样本正确相加,我唯一能想到的就是会导致计算这样一个不正确的总和,因为我的sum
变量(称为{{ 1}})。这引出了我的问题:有没有办法用Java表示比使用BigDecimal更多位的小数?我已经在使用BigDecimal了,除非我做错了,否则似乎没有提供足够的位数。
我必须克服BigDecimal限制的想法是手动使用像BigDecimal那样的科学记数法,但我会使用BigDecimal作为基数,使用BigDecimal作为比例。唯一的问题是,如果有更好的方法来表示更大的数字,我似乎想要避免很多工作。
让我知道是否有更好的方法来表示需要大量位数的数字,或者我是否做错了什么。我也会接受任何建议。
这是我用来将数字加在一起的代码(减去我必须做的所有检查,首先确保应该添加一个数字):
gainLoss
编辑:这是我用来计算总和的完整代码,按要求:
// gainLoss is the sum of all the numbers
BigDecimal gainLoss = new BigDecimal(0.0);
// data is a 2D Object array of all the data from the CSV file.
// The 2nd column in data is filled with BigDecimal objects
for (int i = 1; i < data.length; i++) // for each data row in data (excluding the header row)
{
// set rowAmt to the value of the number in the current row of the CSV file
BigDecimal rowAmt = (BigDecimal)data[i][2];
// add this row's value to gainLoss
gainLoss = gainLoss.add(rowAmt);
}
答案 0 :(得分:0)
这是一个很长的镜头,但有时如果数字大小不同,你可能遇到这样的问题。解决方案是首先对数字进行排序,然后首先对大对进行区分。如何遇到麻烦的例子:
10E38 + 5 - 10E38
将返回0而不是5.但是
10E38 - 10E38 + 5
将返回5(从左到右进行评估时)。当你以正确的顺序做事时,你不会通过将它添加到10E38(没有足够的位来存储它)来“丢失5”。
但是,“真实世界数据”导致的舍入错误与您遇到的一样大,这是非常不寻常的。您可能以错误的方式解释Excel数据。由于您现在已经澄清了当另一列包含单词“cancel”时您没有添加某些数字,您可能想要通过计算以下公式确认您实际上得到的答案与Excel不同:
=SUM(C1:C4381) - SUMIF(E1:E4381, "cancel", C1:C4381)
可能会发现你的代码是正确的,你对答案(或数据)的假设是错误的......