2

I am writing a program that converts an Octal number to Decimal and Hexadecimal. I wrote a function called OctToInt.

function OctToInt(Value: string): Longint;
var
  i: Integer;
  int: Integer;
begin
  int := 0;
  for i := 0 to Length(Value) do
  begin
    int := int * 8 + StrToInt(Copy(Value, i, 1));
  end;
  Result := int;
end; 

I call this function in this way:

var oct:integer;
begin
 oct:=OctToInt(Edit13.Text);
 Edit15.Text:=IntToStr(oct);
end;

When I type 34 (Octal) the decimal number should be 28 but the program gives me 220. Do you know why?

Also, do you have any idea about a converter OctToHex?

Alberto Rossi
  • 1,800
  • 4
  • 36
  • 58
  • 5
    [`Are you sure you wrote it`](http://www.delphitricks.com/source-code/math/convert_an_octal_number_to_integer.html) :-) ? – TLama Aug 19 '13 at 22:50
  • 2
    I've already saw that too :D – Alberto Miola Aug 19 '13 at 22:52
  • 1
    It could happen, after all giving your variables sensible names isn't widely held belief system. Var int : integer. My eyes are bleeding. – Tony Hopkinson Aug 19 '13 at 23:27
  • 1
    I gave you an answer to both of these questions [here](http://stackoverflow.com/a/16782872/62576) months ago. The same solution that worked for Lazarus works for Delphi. (The code I posted there converts from an integer to any number radix from 2 (binary) to 36, and there's a function that reverses that (from binary or octal back to integer.) – Ken White Aug 20 '13 at 02:10
  • 3
    Any time you call `Copy` and the third parameter is the literal 1, it's a *code smell*. Prefer to use the string's array notation: `Value[i]`. Had you written your code the idiomatic way, it would have failed at run time with an out-of-bounds error, alerting you to the real problem in your code. You also could have figured out the problem if you'd used the debugger: You might have noticed that the loop ran too many times, for example. However, a key to effective debugging is understanding how the code is supposed to work in the first place, which rarely happens when you copy others' code. – Rob Kennedy Aug 20 '13 at 02:43

3 Answers3

7

This code accepts a string with a base-8 representation of an integer, and returns the corresponding integer:

function IntPower(const N, k: integer): integer;
var
  i: Integer;
begin
  result := 1;
  for i := 1 to k do
    result := result * N;
end;

function OctToInt(const Value: string): integer;
var
  i: integer;
begin
  result := 0;
  for i := 1 to Length(Value) do
    inc(result, StrToInt(Value[i]) * IntPower(8, Length(Value) - i));
end;

When it comes to converting an integer to a hexadecimal string representation, you already have IntToHex.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
7

You have to change the start of "your" for with 1.

function OctToInt(Value: string): Longint;
var
  i: Integer;
  int: Integer;
begin
  int := 0;
  for i := 1 to Length(Value) do  //here you need 1, not 0
  begin
    int := int * 8 + StrToInt(Copy(Value, i, 1));
  end;
  Result := int;
end;

The conversion Octal-Hexadecimal could be hard to do, so I suggest you another way:

EditHexadecimal.Text:=(IntToHex(StrToInt(EditInteger.Text),8));  

As you can see here, with this code the EditHexadecimal is the Edit where you put the hexadecimal number. With that line I convert a number from decimal to hexadecimal.

You already have the decimal number because you get it with the function OctToInt, so you don't need more code.

Alberto Miola
  • 4,643
  • 8
  • 35
  • 49
0

i made this formula so you can process octals in batches of 3-digits at a time - it's been tested from 000 through 777 to perfectly generate the decimal integer from octals :

if your octals are in a variable oct and temp placeholder o2

then

(37 < oct % 100)*8 + int(0.08*(oct-(o2=oct%10))+0.7017)*8 + o2

if you wanna further streamline that without the placeholder, then its

(37 < oct%100)*8 + int(0.7017+0.08*(oct-(oct%=10)))*8 + oct

  • the "0.7017" is possibly sin(-10*π/8) or 1/sqrt(2), or just 2^(1/-2), but since i found the formula via regression i'm not 100% sure on this.

Another fast trick is that if all 3 digits are the same number - 222 333 555 etc, simply take the first digit then multiply by 73 (cuz 73 in octal is 111). The sequence chain of multipliers for 2-6 consecutive matching digits are

9, 73, 585, 4681, 37449

(it also happens that within this list, for each x, one of {x-2,x+0,x+2} is prime

RARE Kpop Manifesto
  • 2,453
  • 3
  • 11