0

近々テストがあり、2 進数を 3 つの異なる基数 (8 進数、10 進数、16 進数) に変換する必要があるため、基数コンバーターを作成しています。バイナリ文字列を 10 進数と 16 進数に変換するコードは既に作成しています。

function bintodec(Value:string;dec:TEdit;hexadec:TEdit): Integer;
 var             //dec and hexadec are the TEdits where I will put the result
  i, iValueSize: Integer;
  Edit2,f:TEdit;
begin
  Result := 0;
  iValueSize := Length(Value);
  for i := iValueSize downto 1 do
    begin
      if Value[i] = '1' then Result := Result + (1 shl (iValueSize - i));
    end;
  dec.Text:=(IntToStr(Result));        //dec. number
  hexadec.Text:=(IntToHex(Result,8));  //hexadec. number
end;

ここでわかるように、関数は文字列 (たとえば 10101001) を受け取り、結果を 2 つの異なる編集に入れます。

ここに画像の説明を入力

10 進数を 8 進数に変換する関数を作成しましたが、SpeedButtonCalc.を押すとエラーが発生します。project1 がクラス例外 'External: SIGSEGV' を発生させ、Unit1 の近くに control.inc ページが表示されます。Google で解決策を検索しましたが、有用な回答が見つかりませんでした。

function dec2oct(mystring:Integer): String;
  var
  a: String;
  getal_met_rest : Double;
  Edit2:TEdit;
  begin
    while mystring> 0 do
         begin
            getal_met_rest := getal / 8;
            a:= a + IntToStr(mystring - (trunc(getal_met_rest)*8));
            getal := trunc(getal_met_rest);
         end;
    dec2oct:=ReverseString(a);
    Edit2.text:=dec2oct
  end; 

2 進数から 8 進数への変換方法が見つからなかったので、2 進数から 10 進数に変換したら、関数 を呼び出しますdec2oct。この方法で関数を呼び出します。

var a:smallint;
begin
 bintodec(Edit1.Text,Edit3,Edit4);
 dec2oct(Edit3.Text); //Edit3 contains the number on base 10
end;

私たちを手伝ってくれますか?

4

3 に答える 3

3

これは、C ランタイム ライブラリのitoa関数のように機能する関数で、(Delphi では) 正の整数値Cardinalを 2 ~ 36 の指定された基数に変換します。Delphi 2007 および XE4 でテストされています。

type
  TRadixRange = 2..36;

function ConvertIntToBase(value : Cardinal; Radix : TRadixRange) : string;
const
  Digits: array[0..35] of Char = ('0', '1', '2', '3',
                                  '4', '5', '6', '7',
                                  '8', '9', 'A', 'B',
                                  'C', 'D', 'E', 'F',
                                  'G', 'H', 'I', 'J',
                                  'K', 'L', 'M', 'N',
                                  'O', 'P', 'Q', 'R',
                                  'S', 'T', 'U', 'V',
                                  'W', 'X', 'Y', 'Z');
var
  nIndex : Integer;
begin
  Result := '';
  repeat
    nIndex := value mod radix;
    Result := Digits[nIndex] + Result;
    Value := Value div radix;
  until Value = 0;
end;

楽しみのために、変換を「元に戻す」関数を作成することにしました (別の基数から 10 進数 (基数 10) に戻す)。またatoi、渡される数値の基数を渡す必要があることを除いて、C RTL 関数の後に (非常に大まかに) モデル化されています。

function ConvertBaseToInt(const Value: string; const Radix: TRadixRange): Cardinal;
var
  i: Integer;
  Increment: Byte;
begin
  Result := 0;
  for i := 1 to Length(Value) do
  begin
    case Value[i] of
      '0'..'9': Increment := Ord(Value[i]) - Ord('0');
      'A'..'Z',
      'a'..'z': Increment := Ord(Value[i]) - Ord('A') + 10;
    else
      Increment := 0;
    end;
  end;
  Result := Result * Radix + Increment;
end;

多くの数値入力でテストされていることに注意してください。ただしConvertIntToBase、Windows Calculator がプログラマー モードでサポートしている基数 (2 進数 (基数 2)、8 進数 (基数 8)、10 進数 (基数 10、テストしていません))、および 16 進数のみを検証できます。 (基数 16))、他の基数値をサポートする計算機を持っておらず、手作業で作業を行いたくなかったためです。;-)

ConvertBaseToIntのテスト値を渡し、ConvertIntToBase一方に入ったものが他方から戻ってきたものであることを確認することによってテストされました。IOW、 によって 2 進数に変換された数値はConvertIntToBase、 を実行したときに同じ数値になることConvertBaseToInt

コンソール アプリケーションで次のようなものを使用してテストできます。

var
  TempStr: string;
  Reversed: Integer;
  i: Integer;
  Base: Byte;
const
  FmtStr = 'Value (base %d): %d  %s and back %d';
begin
  for i := 0 to 16 do
  begin
    for Base in [2, 8, 16] do  
    begin
      // Test bin, oct, and hex for a range of values from 0..65536
      TempStr := ConvertIntToBase(1 shl i, Base);
      Reversed := ConvertBaseToInt(TempStr, Base);
      Writeln(Format(FmtStr, [Base, 1 shl i, TempStr, Reversed]));
    end;
  end;
  Readln;
end.
于 2013-05-28T02:15:30.387 に答える
3

通常、このような変換には、文字列または文字配列とビット演算を使用します。例えば:

function Int2Oct(invalue: integer): ShortString;
  const
    tt: array[0..7] of char = ('0', '1', '2', '3', '4', '5', '6', '7');
  var
    tempval: integer;
  begin
    Result := '';
    tempval := invalue;
    if tempval = 0 then
      Result := '0'
    else
      while (tempval <> 0) do
        begin
          Result := tt[(tempval and $7)] + Result;
          tempval := (tempval shr 3);
        end;
  end;

負の数を処理することを期待しない限り、私がテストした短い時間で動作するようです。編集:現在ゼロを処理しています。

于 2013-05-27T19:42:23.767 に答える