base conversion
Author Message base conversion

hey, yet another post.....=)
I am writing a program that takes two numbers, written in a base from 2-10
and then asks the user what operation it wants to do with the numbers
(+,-,/,*) and then asks for an output base.  I can convert the numbers to
the base all right but my problem is converting a base 10 number into the
output base.  I have tried, but there are so many exceptions..here's my
code:

uses crt;
function converter(num1:string;base:integer):integer;
var
temp,final,newnum,error,count,count2,count3,multi:integer;
len:string;
begin
final:=0;
for count:=1 to length(num1) do
begin
temp:=1;
len:=num1[count];
val(len,newnum,error);
count2:=0;
temp:=base*newnum;
if count=length(num1) then
temp:=newnum;
if (count<>length(num1)) and (count<>length(num1)-1) then
repeat
inc(count2);
temp:=temp*base;
until count2=length(num1)-2;
final:=final+temp;
end;
converter:=final;
end;
function converter2(num:integer; outbase:integer):string;
var
multi,temp,counter,count,count2,temp5,temp6,temp2,len:integer;
final,s,temp1,finaltemp,temp7,checker:string;
begin
str(num,temp1);
count:=0;
final:='';

repeat
multi:=1;
repeat
multi:=multi*outbase;
temp:=trunc(num/multi);
until temp=0;
multi:=multi div outbase;
temp2:=multi;
temp:=trunc(num/multi);     {
if temp=0 then
begin
temp6:=temp5-len;
final:=copy(final,1,length(final)-1);
counter:=0;
repeat
final:=final+'0';
inc(counter);
until counter=temp6;
str(num,s);
final:=final+s;
count:=counter-1;
end;                     }
num:=num-temp*multi;
if count=0 then
begin
counter:=2;
repeat
multi:=multi div outbase;
inc(counter);
until multi=1;
temp5:=counter;
end;
{if (num=0) and (count<>0) then
if temp2=outbase and count<>0 then}

str(temp,s);
final:=final+s;
finaltemp:=final;
len:=length(final);
inc(count);
until count=counter;
if final[length(final)]='0' then
begin
for count2:=1 to length(final)-1 do
if final[count2]<>'0' then
checker:=final[count2];
final:=copy(final,1,count2-1);
temp7:=final;
count2:=0;
repeat
final:=final+'0';
inc(count2);
until count2=counter-length(temp7)-1;
final:=final+checker;
end;
converter2:=final;
end;

var
inbase,outbase,newnum,newnum2,i:integer;
num1,num2,istring,temp,newnum3:string;
oper:char;
con:boolean;
begin
write('Please enter an input base (2-10) ');
readln(inbase);
write('Please enter a first integer, written in the input base ');
readln(num1);
write('Please enter the operation (+,-,*,/) ');
readln(oper);
write('Please enter a second integer, written in the input base ');
readln(num2);
write('Please enter an output base (2-10) ');
readln(outbase);
newnum:=converter(num1,inbase);
writeln(newnum);
newnum2:=converter(num2,inbase);
writeln(newnum2);
case oper of
'+': i:=newnum+newnum2;
'-': i:=newnum-newnum2;
'*': i:=newnum*newnum2;
'/': begin
if newnum mod newnum2 <> 0 then
begin
writeln('ERROR: You get a real number when dividing
these numbers');
con:=false;
end
else
begin
i:=newnum div newnum2;
con:=true;
end;
end;
end;
if (con=true) or (oper<>'/') then
begin
newnum3:=converter2(i,outbase);
writeln('Your result is ',newnum3);
end;
readln;
end.

Thanks
Jen

Sat, 20 Sep 2003 06:17:53 GMT  base conversion
On Mon, 02 Apr 2001 22:17:53 GMT, Jen *smiles* =T sez:

Quote:
>hey, yet another post.....=)
>I am writing a program that takes two numbers, written in a base from 2-10
>and then asks the user what operation it wants to do with the numbers
>(+,-,/,*) and then asks for an output base.  I can convert the numbers to
>the base all right but my problem is converting a base 10 number into the
>output base.  I have tried, but there are so many exceptions..

Exceptions?  Not a one from where I'm sitting.  Here's the basic (no
pun intended) idea; see if you can translate to Pascal:

for any base 10 number X converting to base B
divide X by B
remainder becomes 1st digit
divide whole number result by B
remainder becomes 2nd digit
divide whole number result of THAT division process by B
remainder becomes 3rd digit...
Repeat until the amount being divided is zero.

If the remainder amount of any of those operations is less than 10,
just use the digit; if it's 10 or more, use A on up.

Peter B. Steiger
Cheyenne, WY
----
If you reply by email, send it to pbs at com dot
canada (or vice-versa).  All adverti{*filter*}ts will be
returned to your postmaster, eh!

Sat, 20 Sep 2003 08:01:15 GMT  base conversion

Quote:
> hey, yet another post.....=)
> I am writing a program that takes two numbers, written in a base
from 2-10
> and then asks the user what operation it wants to do with the
numbers
> (+,-,/,*) and then asks for an output base.  I can convert the
numbers to
> the base all right but my problem is converting a base 10 number
into the
> output base.  I have tried, but there are so many exceptions..here's
my
> code:

Do you do negative numbers, by the way?

You may not want to convert a base 10 number directly; if you are
storing the thing in an Integer internally, it's not base 10 :)

Anyway, on to the code.

Quote:
> uses crt;

This you don't need. If you want things like GotoXY, or TextColor or
stuff, you need CRT. For ordinary writeln to the screen you don't need
it.

Quote:
> function converter(num1:string;base:integer):integer;
> var
>    temp,final,newnum,error,count,count2,count3,multi:integer;
>    len:string;
> begin
>      final:=0;
>      for count:=1 to length(num1) do
>          begin
>               temp:=1;

This initialisation is unnecessary, since you initialise Temp to base
* NewNum later.

Quote:
>               len:=num1[count];
>               val(len,newnum,error);

Here you convert a digit character in len from Num1 into a value.
NewNum is now the value of that digit. One exception is if error<>0 or
newnum>=base; that would imply someone has entered a bad Num1.

You could use val(num1[count], NewNum, error) but it's OK to use the
extra variable len if using the extra variable makes the code clearer
for you.

Another possibility would be to have a lookup table of digits, e.g.
const
Digits : String = '0123456789ABCDEF';
An array of char would be another possibility but if it's a string you
can use Pos:
NewNum=pos(len,Digits)-1;
A negative NewNum indicates a bad digit. This will be useful when you
go beyond base 10, because Val wouldn't work so well at that point.

Quote:
>               count2:=0;
>               temp:=base*newnum;
>               if count=length(num1) then
>                  temp:=newnum;
>               if (count<>length(num1)) and (count<>length(num1)-1)
then
>                  repeat
>                     inc(count2);
>                     temp:=temp*base;
>                  until count2=length(num1)-2;
>               final:=final+temp;

Now, here you are making Temp to be the value of the digit, taking the
base into account. This could be neater. You want to get NewNum and
multiply it by Base enough times, where enough is 0..length(num1)-1
depending on the position of the digit in the number. So the above
chunk of code could be replaced by
For temp := count to length(Num1)-1 do
NewNum := NewNum*Base;
final:=final+NewNum;
(which uses temp for a loop counter instead of a value).

But even that is more work at run-time than is necessary. If you just
multiply Final by Base once for every digit, you will be multiplying
everything by the right amount. This is like typing a number into a
calculator: when you press '1' you see '1', when you press '2' you see
'12' and the one is now a 10. If you press '3' you see '123', the one
is now a hundred and the two is now two tens. Each time, the amount on
the screen is multiplied by 10 and the new digit is added. So
Converter would then be

function converter(num1:string;base:integer):integer;
var
final: Integer;
digit: Integer;
error: Integer;
count: Integer;
begin
final:=0;
for count:=1 to length(num1) do
begin
val(num1[count], digit, error);
{ add something here to handle bad digits }
Final := Final*Base+digit;
end;
converter:=final;
end;

Quote:
>          end;
>      converter:=final;
> end;
> function converter2(num:integer; outbase:integer):string;
> var
>    multi,temp,counter,count,count2,temp5,temp6,temp2,len:integer;
>    final,s,temp1,finaltemp,temp7,checker:string;
> begin
>      str(num,temp1);
>      count:=0;
>      final:='';

>      repeat
>            multi:=1;
>            repeat
>                  multi:=multi*outbase;
>                  temp:=trunc(num/multi);
>            until temp=0;
>            multi:=multi div outbase;
>            temp2:=multi;
>            temp:=trunc(num/multi);     {
>            if temp=0 then
>            begin
>                    temp6:=temp5-len;
>                    final:=copy(final,1,length(final)-1);
>                    counter:=0;
>                    repeat
>                          final:=final+'0';
>                          inc(counter);
>                    until counter=temp6;
>                    str(num,s);
>                    final:=final+s;
>                    count:=counter-1;
>               end;                     }
>            num:=num-temp*multi;
>            if count=0 then
>               begin
>                    counter:=2;
>                    repeat
>                          multi:=multi div outbase;
>                          inc(counter);
>                    until multi=1;
>                    temp5:=counter;
>               end;
>            {if (num=0) and (count<>0) then
>            if temp2=outbase and count<>0 then}

>            str(temp,s);
>            final:=final+s;
>            finaltemp:=final;
>            len:=length(final);
>            inc(count);
>      until count=counter;

Ah no. What does it mean to put a number into base 10 (say)? You start
with a number, which counts something, say nails. You start putting
the nails into boxes of 10 (the base), and you have 3 left over. Then
you put your boxes of nails into boxes 10 times bigger (100); you have
2 left over (20 nails). Then you start filling boxes 10 times bigger
(1000), but you don't fill any of those, you only have 1 of the 100's
boxes... so you have 123 nails. Sorry for stating the obvious but
that's what you do in the code too. You divide what you have into 10s,
and the remainder is the next digit. Each time you have fewer things
to divide, but they matter more because they hold 10 times as many
nails. In your program, "matters more" just means "has a different
position in the output string" so there's no heavy lifting.

So:
const
Digits : String = '0123456789ABCDEF';
function converter2(num:integer; outbase:integer):string;
Var
NextDigit : Integer;
final : String;
Begin
final := '';
Repeat
NextDigit := num mod outbase;
final := Digits[NextDigit+1]+Final;
num := num div outbase;
until num=0;
converter2 := final;
end;

Digits is outside Converter2 so that Converter can use it too :)
Actually, an array [0..MaxBase-1] would be slightly more convenient
here; the '+1' in 'Digits[NextDigit+1]' is because Digits is the
length byte, so Digits='0', Digits='1' and so on.

So each time through the loop, num div outbase effectively divides num
into boxes that are 10 (or whatever the base is) times bigger than the
last time, and num mod outbase gets the smaller boxes that are left
over. These are recorded in Final already, we only have to add on the
next digit each time.

And since we use Repeat...Until, final will definitely get a digit,
even if Num is 0 going in. That will be the only case where the first
digit of final is 0, because the loop ends when Num is 0 after the
divisions. If you want to pad with leading zeros to some length,
change the "Until" condition, e.g.
until (num=0) or (Length(final)>=4);

This next bit confuses me. Is it supposed to lose leading zeros or
something? If so, it's better not to make too many leading zeros in
the first place :P

Quote:
>      if final[length(final)]='0' then
>         begin
>              for count2:=1 to length(final)-1 do
>                  if final[count2]<>'0' then
>                     checker:=final[count2];
>              final:=copy(final,1,count2-1);

Actually, count2 is undefined here, after the For loop. Your current
compiler will set it to some value, but only as a byproduct of the
loop mechanism; the next compiler you buy might do it differently and
leave a different value.

Quote:
>              temp7:=final;
>              count2:=0;
>              repeat
>                    final:=final+'0';
>                    inc(count2);
>              until count2=counter-length(temp7)-1;
>              final:=final+checker;
>         end;
>      converter2:=final;
> end;

Cheers

FP

Sat, 20 Sep 2003 17:54:50 GMT  base conversion

Quote:
>hey, yet another post.....=)
>I am writing a program that takes two numbers, written in a base from 2-10
>and then asks the user what operation it wants to do with the numbers
>(+,-,/,*) and then asks for an output base.  I can convert the numbers to
>the base all right but my problem is converting a base 10 number into the
>output base.  I have tried, but there are so many exceptions..here's my
>code:

>uses crt;
>function converter(num1:string;base:integer):integer;

Come on? Please use better names for the functions. This could
be for example Value().

Also use at least longint for the result. Integer allows only up
to 32767.

Quote:
>var
>   temp,final,newnum,error,count,count2,count3,multi:integer;
>   len:string;
>begin
>     final:=0;
>     for count:=1 to length(num1) do
>         begin
>              temp:=1;
>              len:=num1[count];
>              val(len,newnum,error);

use: newnum:=ord(num1[count])-ord('0'));

Quote:
>              count2:=0;
>              temp:=base*newnum;

What???

Just use: final:=base*final+newnum;

like in base 10, lets say final is thus far 123 and newnum is 4,
you get 1234

Quote:
>              if count=length(num1) then
>                 temp:=newnum;
>              if (count<>length(num1)) and (count<>length(num1)-1) then
>                 repeat
>                    inc(count2);
>                    temp:=temp*base;
>                 until count2=length(num1)-2;
>              final:=final+temp;

What? All this is unnecessary. I cannot make head or tail of the
above. Maybe you intend somehow to put the newnum in its correct
place directly. This could work if the loop ran from last to
first but the correct way is to just do final:=final*base+newnum;

Quote:
>         end;
>     converter:=final;
>end;
>function converter2(num:integer; outbase:integer):string;
>var
>   multi,temp,counter,count,count2,temp5,temp6,temp2,len:integer;
>   final,s,temp1,finaltemp,temp7,checker:string;

Come on? temp5, temp7???? Even that shows there is something
seriously wrong.

Quote:
>begin
>     str(num,temp1);

Why????

Quote:
>     count:=0;
>     final:='';

>     repeat
>           multi:=1;
>           repeat
>                 multi:=multi*outbase;
>                 temp:=trunc(num/multi);

Do not use reals in an integer problem. What you want is
temp:=num div multi;

[much of strange code deleted]

Delete this all immediately and start from the scratch. In
output you should start from the last number. The way do do is:

Take number modulo base, store it somewhere, divide by base and
repeat this until the result of the division is zero. Then just
read the stored info in reversed order. If you use string
concatenation to store the numbers, you will automatically end
with the correct result. I will not write it here but the whole
function needs just 6 lines of code. Both of these problems are
much much much simpler than you think.

Also note that the value() should check for errors.

Osmo

Wed, 01 Oct 2003 01:13:28 GMT

 Page 1 of 1 [ 4 post ]

Relevant Pages

Powered by phpBB® Forum Software