Pounds, Shillings, Pence
April 7, 2015
Mixed-radix number systems have a base, or radix, that varies at each position. For instance, the old-style British pounds, shillings and pence form a mixed-radix system where there are twelve pence in a shilling and twenty shillings in a pound, and calendars form a mixed-radix system where there are sixty seconds in a minute, sixty minutes in an hour, twenty-four hours in a day, and seven days in a week.
Your task is to write a program that accepts a definition of a mixed-radix system — for instance, (7 24 60 60) for the calendar mentioned above — and performs addition and subtraction of numbers written in that system. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
In Python.
fix markup?
really
Nice little problem. Here’s a solution using C arrays, handling carries and borrows as in normal decimal addition. Input can be non-normalized, but the output is always normalized (so adding or subtracting zero normalizes a number). Least significant digit first (though I’ve printed the digits in the opposite order):
radixadd and radixsub should return void there (I missed -Wall off the compilation line).
Solution in Java. However, leading zero’s are not removed..
An example in ISO Prolog (gprolog):
:- initialization(main).
main :-
% Weeks, days, hours, minutes, seconds
Number is 7*24*60*60-1, % 1 second less than 1 week
mixed_radix_number([52,7,24,60,60], Ns, Number),
format(‘~d weeks, ~d days, ~d hours, ~d minutes, and ~d seconds~n’, Ns),
Hourm1sec = [0,0,1,0,-1], % 1 second less than 1 hour
mixed_radix_number([52,7,24,60,60], Hourm1sec, Secs),
mixed_radix_number([52,7,24,60,60], Nd, Secs),
format(‘1 second less than 1 hour ~w = ~w = ~d seconds~n’,
[Hourm1sec,Nd,Secs]),
Ym1sec = [364,0,0,-1], % 1 year – 1 second, but 7*52 = 364
mixed_radix_number([365,24,60,60],Ym1sec,S),
mixed_radix_number([365,24,60,60],Ym1sec,S),
mixed_radix_number([52,7,24,60,60],Yw,S),
format(‘1 second less than 1 year in days and time: ~w~n’,[Ym1sec]),
format(‘1 second less than 1 year in weeks, days and time: ~w~n’,
[Yw]),
format(‘ 7 weekdays * 52 weeks in days: 364~n’,[]),
format(‘1 second less than 1 year in seconds: ~d~n’,[S]),
% Pounds, shillings, pence
mixed_radix_number([999999,20,12],[8,12,10],Pence),
format(‘~d £, ~d shillings, and ~d pence are ~d pence total~n’,
[8,12,10,Pence]),
mixed_radix_number([1000,20,12],Ps,Pence),
format(‘~d pence are ~d £, ~d shillings, and ~d pence~n’,[Pence|Ps]),
mixed_radix_number([1000,20,12],[8,12,10],Pence),
% Degrees, minutes, seconds
mixed_radix_number([360,60,60],[53,45,20],Seconds),
format(’53 degrees 45”20”” W is ~d seconds west~n’,[Seconds]),
% Binary numbers
mixed_radix_number([2,2,2,2,2,2,2,2],B,67),
format(’67 in a binary (octet) is ~w~n’,[B]),
% Hexadecimal numbers
mixed_radix_number([16,16],[7,15],Hx),
format(‘7F hexadecimal is ~d decimal~n’, [Hx]),
mixed_radix_number([16,16],Hx1,254),
format(‘254 decimal is ~w hexadecimal~n’, [Hx1]),
halt.
% mixed_radix_number(+Radices, +Mixed, ?Number)
% mixed_radix_number(+Radices, -Mixed, +Number)
mixed_radix_number(Rs, Ns, S) :- nonvar(Ns), !,
decoded_mixed_radix_number(Rs, Ns, 0, S).
mixed_radix_number(Rs, Ns, S) :- var(Ns),
reverse(Rs, Rs1),
encoded_mixed_radix_number(Rs1, [], Ns, S).
decoded_mixed_radix_number([], [], S, S).
decoded_mixed_radix_number([R|Rs], [N|Ns], S0, S) :-
S1 is R * S0 + N,
decoded_mixed_radix_number(Rs, Ns, S1, S).
encoded_mixed_radix_number([], Ns, Ns, _S).
encoded_mixed_radix_number([R|Rs], Ns0, Ns, S) :-
Rem is S mod R,
S1 is floor(S / R),
encoded_mixed_radix_number(Rs, [Rem|Ns0], Ns, S1).
[/source/
Alas, try again to get formatting right:
Have mercy, this does not bode well, 3rd time: