3

整数をlong_integerに変換し、long_integerをPositive_Countに変換する方法を考えています。その場合、変換は簡単なはずですが、私が試したすべての方法でエラーが発生しました。

たとえば、

long := long_integer(int1) + long_integer(int2);

両方の整数が正であったとしても、長い場合は負の値になります。

私が実行している関数のコード、デバッグのために分割されたステップ:

--calcKey--
procedure calcKey(x: in String16; key: out External_IO.Positive_Count) is
  s1, s2 : String2;
  int1, int2 : integer;
  long1, long2 : long_integer;
begin
  s1 := x(12..13); 
  s2 := x(15..16); 
  put_line("s1: " &s1& "- s2: " &s2);
  int1 := abs StringToInt(s1);
  int2 := abs StringToInt(s2); 
  put("int1: " & Integer'image(int1) & " | int: " & Integer'Image(int2)); new_line;
  long1 := long_integer(int1); 
  long2 := long_integer(int2);
  long1 := long1 + long2; 
  put_line("long := " & long_integer'Image(long1));
  long1 := (long1 mod 256) + 1;
  key := External_IO.Positive_Count(long1); 
  put_line("Key : " & External_IO.Positive_Count'Image(key));

  new_line;
end calcKey;

関数の呼び出し:

calcKey("0123456789abcdef",k);
calcKey("0123456789abcdef",k);
calcKey("0123456789abcdef",k);
calcKey("0123456789abcdef",k);
calcKey("fedvba9876543210",k);
calcKey("fedvba9876543210",k);

出力:

s1: bc- s2: ef
int1:  2011929758 | int:  1667393125
long := -615644413
Key :  4

s1: bc- s2: ef
int1:  287586 | int:  1667393125
long :=  1667680711
Key :  200

s1: bc- s2: ef
int1:  13132642 | int:  1667393125
long :=  1680525767
Key :  200

s1: bc- s2: ef
int1:  13132642 | int:  1667393125
long :=  1680525767
Key :  200

s1: 43- s2: 10
int1:  13120308 | int:  859058225
long :=  872178533
Key :  102

s1: 43- s2: 10
int1:  6697780 | int:  859058225
long :=  865756005
Key :  102
4

2 に答える 2

4

前の答えは、整数サイズをチェックする必要性(および正しい方法)については正しいです。

または、独自の整数型を定義して、「問題」を解決してください。

ただし、整数の加算がオーバーフローして負の数を返す場合は、Adaコンパイラを使用していません。

GnatがデフォルトでAdaコンパイラではないのは残念です。

Gnatでは、オーバーフローなどのチェックを有効にするためにコンパイラフラグを設定する必要があります。これは、デフォルトで実際にオンになっているはずです。次に、そのようなオーバーフローにより、失敗したコード行を直接指すメッセージでConstraint_Error例外が発生します。これにより、問題をリバースエンジニアリングするよりもはるかに簡単にテストできます。

gnatmake -gnataeEfoUv -fstack-check my_main.adb

はかなり包括的なセットであり、おそらく不要なスタイルチェックが含まれています。詳細については、Gnatのドキュメントを確認してください。

優先フラグセットに関するその他の提案を歓迎します。

別のコンパイラを使用している場合は、それがどれであるかを知りたいと思います。

ちなみに、あなたはStringToInt関数を提供していないので、他の誰もあなたの例をテストすることはできませんが、それが生成する値は、あなたが提供する文字列から期待する値とはまったく異なることを指摘します...それはランダムハッシュですか発生器?

于 2012-12-04T10:50:24.243 に答える
3

(これはコメントであるはずですが、長すぎるので回答として提出します)

私が最初にすることは、long_intがあなたが思っているものであることを実際に確認することです。つまり、実行INTEGER'SIZELONG_INTEGER'SIZEていることです。プラットフォーム上では、それらがまったく同じサイズである可能性があります。

エイダの定義から:

これらのタイプの範囲とサイズは、プラットフォームごとに異なる可能性があることに注意してください(もちろん、ブール値と[[Wide_] Wide_] Characterを除く)。タイプIntegerのサイズが少なくとも16ビットであり、Long_Integerのサイズが少なくとも32ビット(存在する場合)RM 3.5.4(21..22)(注釈付き)であるという実装要件があります。したがって、型の完全な移植性が必要な場合は、標準の型を使用せず(必要な場合を除き、以下を参照)、独自の型を定義してください。コンパイラーは、範囲が満たされない型宣言を拒否します。

それらが同じサイズである場合、2つの非常に大きなintを追加するとオーバーフローする可能性があり、結果が表示されます。

出典: http: //en.wikibooks.org/wiki/Ada_Programming/Libraries/Standard

于 2012-12-04T06:38:20.983 に答える