001 package aima.util; 002 003 import java.util.List; 004 005 /** 006 * @author Ciaran O'Reilly 007 * see: http://demonstrations.wolfram.com/MixedRadixNumberRepresentations/ 008 * for useful example. 009 */ 010 public class MixedRadixNumber extends Number { 011 // 012 private static final long serialVersionUID = 1L; 013 // 014 private long value = 0L; 015 private long maxValue = 0L; 016 private int[] radixs = null; 017 private int[] currentNumeralValue = null; 018 private boolean recalculate = true; 019 020 public MixedRadixNumber(long value, int[] radixs) { 021 this.value = value; 022 this.radixs = new int[radixs.length]; 023 System.arraycopy(radixs, 0, this.radixs, 0, radixs.length); 024 calculateMaxValue(); 025 } 026 027 public MixedRadixNumber(long value, List<Integer> radixs) { 028 this.value = value; 029 this.radixs = new int[radixs.size()]; 030 for (int i = 0; i < radixs.size(); i++) { 031 this.radixs[i] = radixs.get(i); 032 } 033 calculateMaxValue(); 034 } 035 036 public long getMaxAllowedValue() { 037 return maxValue; 038 } 039 040 public boolean increment() { 041 if (value < maxValue) { 042 value++; 043 recalculate = true; 044 return true; 045 } 046 047 return false; 048 } 049 050 public boolean decrement() { 051 if (value > 0) { 052 value--; 053 recalculate = true; 054 return true; 055 } 056 return false; 057 } 058 059 public int getCurrentNumeralValue(int atPosition) { 060 if (atPosition >= 0 && atPosition < radixs.length) { 061 if (recalculate) { 062 long quotient = value; 063 for (int i = 0; i < radixs.length; i++) { 064 if (0 != quotient) { 065 currentNumeralValue[i] = (int) quotient % radixs[i]; 066 quotient = quotient / radixs[i]; 067 } else { 068 currentNumeralValue[i] = 0; 069 } 070 071 } 072 recalculate = false; 073 } 074 return currentNumeralValue[atPosition]; 075 } 076 throw new IllegalArgumentException("Argument atPosition must be >=0 and < "+radixs.length); 077 } 078 079 // 080 // START-Number 081 public int intValue() { 082 return (int) longValue(); 083 } 084 085 public long longValue() { 086 return value; 087 } 088 089 public float floatValue() { 090 return longValue(); 091 } 092 093 public double doubleValue() { 094 return longValue(); 095 } 096 // END-Number 097 // 098 099 public String toString() { 100 StringBuilder sb = new StringBuilder(); 101 102 for (int i = 0; i < radixs.length; i++) { 103 sb.append("["); 104 sb.append(this.getCurrentNumeralValue(i)); 105 sb.append("]"); 106 } 107 108 return sb.toString(); 109 } 110 111 // 112 // PRIVATE 113 // 114 private void calculateMaxValue() { 115 if (0 == radixs.length) { 116 throw new IllegalArgumentException("At least 1 radix must be defined."); 117 } 118 for (int i = 0; i < radixs.length; i++) { 119 if (radixs[i] < 2) { 120 throw new IllegalArgumentException("Invalid radix, must be >= 2"); 121 } 122 } 123 124 // Calcualte the maxValue allowed 125 maxValue = radixs[0]; 126 for (int i = 1; i < radixs.length; i++) { 127 maxValue *= radixs[i]; 128 } 129 maxValue -= 1; 130 131 if (value > maxValue) { 132 throw new IllegalArgumentException("The value ["+value+"] cannot be represented with the radixs provided, max value is " + maxValue); 133 } 134 135 currentNumeralValue = new int[radixs.length]; 136 } 137 }