Solved

Debug Java BigDecimal in Eclipse

Posted on 2013-11-05
3
1,045 Views
Last Modified: 2013-11-05
Hi,

I have been debugging some code recently using eclipse and I came across something that I can't explain and wanted to get an answer.  The following is a JUnit test that is successful.  When I attempted to debug it I get an odd result in the debug screen for csp at the end.  I would expect the intCompact to be: 231246....... , but it is -9223372036854775808. Yet the test is successful.

What am I missing?

import static org.junit.Assert.assertEquals;

import java.math.BigDecimal;

import org.junit.Test;

public class BigDecimalTest {


	@Test
	public void Test1() {
		BigDecimal opp = new BigDecimal("1.5");
		BigDecimal liq = new BigDecimal("1.5");
		BigDecimal div = new BigDecimal("0.08");
		
		assertEquals("",2.25d,opp.multiply(liq).doubleValue(),0d);
		assertEquals("",1.5d,opp.doubleValue(),0d);
		
		assertEquals("",.12d,opp.multiply(div).doubleValue(),0d);

		//Date startDate = new Date("5/9/2013");
		//Date endDate = new Date("11/15/2013");
		//BigDecimal years = startDate.getYearsBetweenBigDecimal(endDate);
		//assertEquals("",5.20547945205479E-01,years.doubleValue(),1E-14);
		BigDecimal years = new BigDecimal(5.20547945205479E-01);

		BigDecimal dsp = opp.multiply(years).multiply(div);
		assertEquals("",6.24657534246575E-02,dsp.doubleValue(),1E-14);
		
		BigDecimal csp = opp.multiply(liq);
		csp = csp.add(dsp);
		
		assertEquals("",2.31246575342466E+00,csp.doubleValue(),1E-14);
	}
	
}

Open in new window

0
Comment
Question by:infinidem
  • 2
3 Comments
 
LVL 26

Expert Comment

by:dpearson
ID: 39625153
Is your goal here to understand how BigDecimal is implemented?

intCompact is an internal part of the representation which BigDecimal can decide to use when it believes the value can be safely represented as an integer (long actually).

However, if the value being represented by BigDecimal is outside that range (or it believes it may be - such as doing a multiplication) then intCompact may no longer be in use - so checking the value can show you garbage essentially.

At that point, BigDecimal relies on intValue instead, which is itself a BigInteger and intCompact is ignored.

Does that make sense?

If you want to learn more about exactly how BigDecimal is processing these calculations, you can set a breakpoint inside the BigDecimal source code and step through it to see how the multiply and add operations are being implemented in this case.

Hope that helps,

Doug
0
 

Author Comment

by:infinidem
ID: 39625315
Interesting.  From the rt.jar file I did find this that relates to what Doug said.

static final long INFLATED = -9223372036854775808L

Open in new window


Which indicates that the values I am working with did hit the INFLATED threshold.  Okay in this example it does quickly go out to 56 decimal points, which would easily put it over the threshold.  From the source code I see that it would put it into a BigInteger.  Taking a look at the Debug I can see the intCompact is "Set" to inflated which means it is coming from intVal (BigInteger).  Then BigInteger is using an array of type int.  Which is supposingly in Big Endian.  Yet how would 158225327 translate into 231246...

csp	BigDecimal  (id=72)	
	intCompact	-9223372036854775808	
	intVal	BigInteger  (id=74)	
		bitCount	0	
		bitLength	0	
		firstNonzeroIntNum	0	
		lowestSetBit	0	
		mag	 (id=75)	
			[0]	158225327	
			[1]	-1753700659	
			[2]	1201931299	
			[3]	-1388385198	
			[4]	-1612795011	
			[5]	446100184	
		signum	1	
	precision	0	
	scale	56	
	stringCache	"2.31246575342465747748832427532761357724666595458984375000" (id=76)	

Open in new window

0
 
LVL 26

Accepted Solution

by:
dpearson earned 500 total points
ID: 39625341
The docs indicate that this is a form of "narrowing primitive conversion" as described here:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3

From a more practical standpoint, the toString() method in BigInteger is in some sense the gold standard for how the internal representation is turned back into a number that you can look at.  If you want to spend the time to work through this it will explain (implicitly) how the underlying representation works:

    public String toString(int radix) {
	if (signum == 0)
	    return "0";
	if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
	    radix = 10;

	// Compute upper bound on number of digit groups and allocate space
	int maxNumDigitGroups = (4*mag.length + 6)/7;
	String digitGroup[] = new String[maxNumDigitGroups];
        
	// Translate number to string, a digit group at a time
	BigInteger tmp = this.abs();
	int numGroups = 0;
	while (tmp.signum != 0) {
            BigInteger d = longRadix[radix];

            MutableBigInteger q = new MutableBigInteger(),
                              a = new MutableBigInteger(tmp.mag),
                              b = new MutableBigInteger(d.mag);
            MutableBigInteger r = a.divide(b, q);
            BigInteger q2 = q.toBigInteger(tmp.signum * d.signum);
            BigInteger r2 = r.toBigInteger(tmp.signum * d.signum);

            digitGroup[numGroups++] = Long.toString(r2.longValue(), radix);
            tmp = q2;
	}

	// Put sign (if any) and first digit group into result buffer
	StringBuilder buf = new StringBuilder(numGroups*digitsPerLong[radix]+1);
	if (signum<0)
	    buf.append('-');
	buf.append(digitGroup[numGroups-1]);

	// Append remaining digit groups padded with leading zeros
	for (int i=numGroups-2; i>=0; i--) {
	    // Prepend (any) leading zeros for this digit group
	    int numLeadingZeros = digitsPerLong[radix]-digitGroup[i].length();
	    if (numLeadingZeros != 0)
		buf.append(zeros[numLeadingZeros]);
	    buf.append(digitGroup[i]);
	}
	return buf.toString();
    }

Open in new window


Doug
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
groupSumClump challenge 9 115
github account with ecipse 1 47
varialbe initialization 11 32
Java exception bubble up 2 17
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.

813 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now