Does anyone know if this is a Java library bug?

雨燕双飞 提交于 2019-12-11 12:38:31

问题


** 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!