9

How do you convert a decimal number to mixed radix notation?

I guess that given an input of an array of each of the bases, and the decimal number, it should output an array of the values of each column.

nickf
  • 537,072
  • 198
  • 649
  • 721

5 Answers5

7

Pseudocode:

bases = [24, 60, 60]
input = 86462                       #One day, 1 minute, 2 seconds
output = []

for base in reverse(bases)
    output.prepend(input mod base)
    input = input div base          #div is integer division (round down)
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
Artelius
  • 48,337
  • 13
  • 89
  • 105
3

Number -> set:

factors = [52,7,24,60,60,1000]
value = 662321
for i in n-1..0
  res[i] = value mod factors[i]
  value = value div factors[i]

And the reverse:

If you have the number like 32(52), 5(7), 7(24), 45(60), 15(60), 500(1000) and you want this converted to decimal:

Take number n, multiply it with the factor of n-1, continue for n-1..n=0

values = [32,5,7,45,15,500]
factors = [52,7,24,60,60,1000]

res = 0;
for i in 0..n-1
  res = res * factors[i] + values[i]

And you have the number.

Toon Krijthe
  • 52,876
  • 38
  • 145
  • 202
  • The question asks for the opposite of this. – Artelius Apr 17 '09 at 07:09
  • Toon, the solution you proposed for encoding a decimal value to a mixed-radix representation seems correct, however, the reverse, i.e. your solution to decoding a mixed-radix number-representation to its decimal value seems incorrect. The correct solution would be: `values = [32,5,7,45,15,500]; factors = [52,7,24,60,60,1000]; res = 0; base = 1; for i in n-1..0 { res = res + (values[i] * base); base = base * factors[i]; }` – Dániel László Kovács Apr 28 '22 at 04:34
2

In Java you could do

public static int[] Number2MixedRadix(int[] base, int number) throws Exception {
            //NB if the max number you want @ a position is say 3 then the base@ tha position
            //in your base array should be 4 not 3

            int[] RadixFigures = new int[base.length];
            int[] PositionPowers = new int[base.length];
            PositionPowers[base.length-1] = 1;
            for (int k = base.length-2,pow = 1; k >-1; k--){
                pow*=base[k+1];
                PositionPowers[k]=pow;
            }for (int k = 0; k<base.length; k++){
                RadixFigures[k]=number/PositionPowers[k];
                if(RadixFigures[k]>base[k])throw new Exception("RadixFigure@["+k+"] => ("+RadixFigures[k]+") is > base@["+k+"] => ("+base[k]+") | ( number is Illegal )");
                number=number%PositionPowers[k];
            }return RadixFigures;
        }

Example

//e.g. mixed-radix base for 1day
int[] base = new int[]{1, 24, 60, 60};//max-day,max-hours,max-minutes,max-seconds
int[] MixedRadix = Number2MixedRadix(base, 19263);//19263 seconds
//this would give [0,5,21,3] => as per 0days 5hrs 21mins 3secs

Reversal

 public static int MixedRadix2Number(int[] RadixFigures,int[] base) throws Exception {
            if(RadixFigures.length!=base.length)throw new Exception("RadixFigures.length must be = base.length");
            int number=0;
            int[] PositionPowers = new int[base.length];
            PositionPowers[base.length-1] = 1;
            for (int k = base.length-2,pow = 1; k >-1; k--){
                pow*=base[k+1];
                PositionPowers[k]=pow;
            }for (int k = 0; k<base.length; k++){
                number+=(RadixFigures[k]*PositionPowers[k]);
                if(RadixFigures[k]>base[k])throw new Exception("RadixFigure@["+k+"] => ("+RadixFigures[k]+") is > base@["+k+"] => ("+base[k]+") | ( number is Illegal )");
            }return number;
        }
linker
  • 821
  • 1
  • 8
  • 20
1

I came up with a slightly different, and probably not as good method as the other ones here, but I thought I'd share anyway:

    var theNumber = 313732097; 
    
    //             ms   s   m   h    d
    var bases = [1000, 60, 60, 24, 365];
    var placeValues = [];  // initialise an array
    var currPlaceValue = 1;
    
    for (var i = 0, l = bases.length; i < l; ++i) {
        placeValues.push(currPlaceValue);
        currPlaceValue *= bases[i];
    }
    console.log(placeValues);
    // this isn't relevant for this specific problem, but might
    // be useful in related problems.
    var maxNumber = currPlaceValue - 1;
    
    
    var output = new Array(placeValues.length);
    
    for (var v = placeValues.length - 1; v >= 0; --v) {
        output[v] = Math.floor(theNumber / placeValues[v]);
        theNumber %= placeValues[v];
    }
    
    console.log(output);
    // [97, 52, 8, 15, 3] --> 3 days, 15 hours, 8 minutes, 52 seconds, 97 milliseconds
phuclv
  • 37,963
  • 15
  • 156
  • 475
nickf
  • 537,072
  • 198
  • 649
  • 721
  • I think you can use Math.DivRem in your second loop. output[v]=Math.DivRem(theNumber,placeValues[v],out theNumber); – Hafthor Aug 21 '09 at 16:26
0

I tried a few of the examples before and found an edge case they didn't cover, if you max out your scale you need to prepend the result from the last step

def intToMix(number,radix=[10]):
    mixNum=[]

    radix.reverse()
    for i in range(0,len(radix)):
        mixNum.append(number%radix[i])
        number//=radix[i]
    mixNum.append(number)
    mixNum.reverse()
    radix.reverse()
    return mixNum


num=60*60*24*7

radix=[7,24,60,60]

tmp1=intToMix(num,radix)