You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by "Alexey Petrenko (JIRA)" <ji...@apache.org> on 2007/01/30 15:18:33 UTC

[jira] Assigned: (HARMONY-3086) [math] poor hashCode in java.math.BigDecimal and java.math.BigDecimal

     [ https://issues.apache.org/jira/browse/HARMONY-3086?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Alexey Petrenko reassigned HARMONY-3086:
----------------------------------------

    Assignee: Alexey Petrenko

> [math] poor hashCode in java.math.BigDecimal and java.math.BigDecimal
> ---------------------------------------------------------------------
>
>                 Key: HARMONY-3086
>                 URL: https://issues.apache.org/jira/browse/HARMONY-3086
>             Project: Harmony
>          Issue Type: Improvement
>          Components: Classlib
>         Environment: Platform independent
>            Reporter: Evgeniya Maenkova
>         Assigned To: Alexey Petrenko
>         Attachments: HashMapTest.java, math.patch
>
>
> As BigDecimal/BigInteger.hashCode isn't specified I belive we can do some improvements in this arrea.
> 1)BigInteger.hashCode computes a hash code accordingly to the latest digit only. We could take all digits into account.
> 2)BigDecimal.hashCode uses shift, so BigInteger's hashCode has pretty small influence on BigDecimal's hashCode.
>  public int hashCode() {
>         /* Take the 24 trailing bits of BigInteger hashcode
>          * and the 8 trailing bits of scale. */
>         return ((getUnscaledValue().hashCode() << 24) | (0xFF & scale));
>     }
> 3) when we are dealing with "small" BigDecimal I believe it's possible to compute hash code more effectively without redudant objects creation (I mean BigInteger).
> 4) I've written minimal test case with "big" BigDecimal as keys in some hashMap(to be attached, and see please below) and there the results (my laptop :), pretty approximately, of course):
> RI:
> --
> different hash coodes: 45000
> time6173
> --
> current java.math:
> different hash coodes: 906
> time82239
> --patched java.math:
> different hash coodes: 45000
> time6344
> (This test shows so big difference in time and hash code distribution.
> 5)I get 1 failed test with this patch:org.apache.harmony.tests.java.math.BigIntegerHashCodeTest. Test is looking doubtful as (a) hash code isn;t specified so we shouldn't require this behavior; (b) It fails on RI also. So I would propose to remove this test at all.
> -    public void testUnequalObjectsEqual() {
> -        byte aBytes[] = {56, 100, -2, -76, 98, 54, 19, 3, -15, 45, 89, -111, 69, 103, 8, -9};
> -        byte bBytes[] = {56, 100, -2, -76, 89, 45, 91, 3, -15, 45, 89, -111, 69, 103, 8, -9};
> -        int aSign = 1;
> -        BigInteger aNumber = new BigInteger(aSign, aBytes);
> -        BigInteger bNumber = new BigInteger(aSign, bBytes);
> -        int code1 = aNumber.hashCode();
> -        int code2 = bNumber.hashCode();
> -        if (!aNumber.equals(bNumber)) {
> -            assertTrue("hash codes for these unequal objects should be equal", code1 == code2);
> -        }
> -    }
> +    }      
> Test  case mentioned above:
> ----
> import java.math.BigDecimal;
> import java.text.NumberFormat;
> import java.util.Arrays;
> import java.util.HashMap;
> import java.util.Random;
> public class HashMapTest {
> 	static class MyBigDecimal extends BigDecimal {
> 		public MyBigDecimal(String s) {
> 			super(s);
> 		}
> 		static long hashCodeCallsCounter;
> 		static long equalsCallsCounter;
> 		@Override
> 		public int hashCode() {
> 			hashCodeCallsCounter ++;
> 			return super.hashCode();
> 		}
> 		
> 		@Override
> 		public boolean equals(Object arg0) {
> 			equalsCallsCounter ++;
> 			return super.equals(arg0);
> 		}
> 		
> 		static void reset() {
> 			equalsCallsCounter = 0;
> 			hashCodeCallsCounter = 0;
> 		}
> 	}
> 	
> 	
> 	static MyBigDecimal[][][] keys;
> 	static int[] hashcodes;
> 	public static HashMap createRatesMap(int dim1, int dim2,
>             int dim3, BigDecimal value1) {
>         HashMap map = new HashMap();
>         keys = new MyBigDecimal[dim1][dim2][dim3];
>         StringBuffer sb = new StringBuffer();
>         NumberFormat nf = NumberFormat.getNumberInstance();
>         nf.setMinimumIntegerDigits(3);
>         hashcodes = new int[dim1 * dim2 * dim3];
>         int ind = 0;
>         for (int i = 0; i < dim1; i ++){
>             for (int j = 0; j < dim2; j ++) {
>                 for (int k = 0; k < dim3; k ++) {
>                     long res = i * 10000 + j * 100 + k;
>                     int scale = 3 + ((i + j + k) % 5);
>                     MyBigDecimal key = new MyBigDecimal(res + "." + res);
>                     keys[i][j][k] = key;
>                     hashcodes[ind ++] = key.hashCode();
>                     map.put(key, value1.setScale(scale, BigDecimal.ROUND_DOWN));
>                 }
>             }
>         }
>         return map;
>     }	
> 	
> 	public static void main(String[] args) {
> 		HashMap map = createRatesMap(300, 10, 15, BigDecimal.ONE);
> 		Arrays.sort(hashcodes);
> 		int currentValue = 0;
> 		int currentIndex = 0;
> 		int curLength = 0;
> 		int[] value = new int[hashcodes.length];
> 		int[] counters = new int[hashcodes.length];
> 		
> 		for (int i = 0; i < hashcodes.length; i ++) {
> 			if (hashcodes[i] == currentValue) {
> 				currentIndex++;
> 				counters[curLength - 1] = currentIndex;				
> 			} else {				
> 				currentIndex = 1;
> 				currentValue = hashcodes[i];
> 				value[curLength] = currentValue;
> 				counters[curLength] = 1;
> 				curLength++;
> 			}
> 		}		
> 		
> 		MyBigDecimal.reset();		
> 		Random random = new Random();	
> 		long start = System.currentTimeMillis();
> 		for (int i = 0; i < 10000000; i ++) {
> 		    map.get(keys[random.nextInt(300)][random.nextInt(10)][random.nextInt(15)]);
> 		}
> 		System.out.println("different hash coodes: " + curLength);
> 		System.out.println("time" + (System.currentTimeMillis() - start));		
> 		
> 	}
> }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.