问题描述
**这是一个更正后的帖子**
** This is a corrected post **
我正在使用BigDecimal进行一些非常复杂的数学计算,并且在数千次测试之一中遇到了错误.有人看到我做错了什么愚蠢的东西吗?我不这么认为.
I'm doing some very intricate math calculations using BigDecimal and ran into an error in ONE of several thousand tests. Does anyone see something stupid that I did wrong? I don't think so.
下面的输出(从原始帖子中更正)是计算得出的几条迹线之一.好像Java只是错误地仅 printing 非BigInteger变量,因为该函数有效-使用x,ix,y和iy.问题是:为什么x的值会从一张打印变为另一张? -似乎我不应该做.
The output below (corrected from original post) is one of several traces from the calculations. It seems as if Java simply is only printing the non-BigInteger variables incorrectly because the function works - using x,ix, y and iy. The question is: why would the value of x change from one print to the next? - it doesn't seem like something I should be able to do.
当我不小心使内部常数pi和e精确到1500个小数位时,发生了错误.在1000个地方,一切都很好,没有错误.
The error occurred when I accidentally made internal constants pi and e accurate to 1,500 decimal places. At 1,000 places, all was fine and no error.
转储中的值x恰好等于= 2 * PI,约为6.283185307179586476925286766559下面是代码段.
The value x in the dump is coincidentally = is 2*PI which is approx 6.283185307179586476925286766559 Below is the snippet.
public static int cmp(BigDecimal x, BigDecimal y, int places)
{
BigInteger ix = x.movePointRight(places).toBigInteger();
String sInt = ix.toString();
BigDecimal shiftX = x.movePointRight(places);
String sx = x.movePointRight(places).toString();
int dot = sx.indexOf('.'); // making the shifted x
if (dot > 0) // string into an integer string
sx = sx.substring(0,dot); // just for comparison
if ( !sx.equals(sInt) )
{
System.out.println("****** cmp(): Mismatch between X values. dec places = " + places);
System.out.println("x = " + x);
System.out.println("x.toString() = " + x.toString());
System.out.println("x.toPlain() = " + x.toPlainString());
System.out.println("x.right() #1 = " + x.movePointRight(places));
System.out.println("x.right() #2 = " + shiftX);
System.out.println("x.right() #3 = " + sx);
String shiftXStr = x.movePointRight(places).toString();
System.out.println("x.right().str() #1 = " + x.movePointRight(places).toString());
System.out.println("x.right().str() #2 = " + shiftXStr);
String shiftXPlain = x.movePointRight(places).toPlainString();
System.out.println("x.right().plain() 1 = " + x.movePointRight(places).toPlainString());
System.out.println("x.right().plain() 2 = " + shiftXPlain);
System.out.println("x.toBigInt() = " + x.toBigInteger());
System.out.println("BigInt(x) #1 = " + x.movePointRight(places).toBigInteger());
System.out.println("BigInt(x) #2 = " + ix);
System.out.println("BigInt(x).str() 1 = " + x.movePointRight(places).toBigInteger().toString());
System.out.println("BigInt(x).str() 2 = " + sInt);
}
输出为:(仅最后一行和从其开始的第二行是正确的.请注意,错误的值始终是正确值的2 ^ n的倍数,包括为简洁起见未显示的测试-我将其截断了便于阅读)
The output is: (only the last line and 2 up from it are correct. note that the wrong values are always a multiple of 2^n of the correct value, including tests not shown for brevity -- and I cut off at right for readability)
****** cmp(): Mismatch between X values. dec places = 595
x = 205887.41614566068967588779676660550101874569
x.toString() = 205887.41614566068967588779676660550101874569
x.toPlain() = 205887.41614566068967588779676660550101874569
x.right() #1 = 205887416145660689675887796766605501018745693
x.right() #2 = 205887416145660689675887796766605501018745693
x.right() #3 = 205887416145660689675887796766605501018745693
x.right().str() #1 = 205887416145660689675887796766605501018745693
x.right().str() #2 = 205887416145660689675887796766605501018745693
x.right().plain() 1 = 205887416145660689675887796766605501018745693
x.right().plain() 2 = 205887416145660689675887796766605501018745693
x.toBigInt() = 205887
BigInt(x) #1 = 205887416145660689675887796766605501018745693
BigInt(x) #2 = 628318530717958647692528676655900576839433879
BigInt(x).str() 1 = 205887416145660689675887796766605501018745693
BigInt(x).str() 2 = 628318530717958647692528676655900576839433879
**我相信只是原始数据中的标签有误.
** I believe it was only the labels that were wrong in the original data.
推荐答案
跟进.我错了上面的答案"仅部分解决了测试程序中的问题.它在实际程序中不起作用.
我意识到这很复杂,但是我确实找到了一个修正了神秘不一致输出的修复程序,这应该令人信服:
我在使用toBigDecimal( )[针对该错误数据]:
x = new BigDecimal(x.toString());
我怀疑BigDecimal的某些属性已损坏.不是规模.
Followup. I was incorrect. The above 'answer' only partly solved the problem in the test program. It did not work in the real program.
I realize this is quite involved, but I did find a fix that corrected the mysterious inconsistent outputs, and this should prove convincing:
I added the following line before using toBigDecimal() [for that wrong data]:
x = new BigDecimal( x.toString() );
I would suspect that some attribute of the BigDecimal has gotten corrupted. It was not the scale.
这篇关于有人知道这是否是Java库错误吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!