问题
** This is a corrected post **
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.
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.
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.
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);
}
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.
回答1:
This probably belongs here.
I must say thanks to everyone who looked at this problem.
I may have stumbled onto the answer, and it was my problem, happily. I found an error in my test program and fixing it cleared up the problem above. The problem I was really after also went away but for some reason the diagnostic traces still print inconsistent values like those above, which is still a mystery.
The whole problem seems to have something to do with an inheriting class's static initializations not happening in the order I'm thinking - in one case.
回答2:
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.
来源:https://stackoverflow.com/questions/28878857/does-anyone-know-if-this-is-a-java-library-bug