2012.02.20
 

CHGVARが文書化されていない

今から約 1 か月半前、base-10 から base-41 に変換するため、 CL でモジュールを作成していました。(他ならぬ CL で、こうした難題に取り組んでいた理由は、いつかそれ自体が優れたヒントになるかもしれないと思ったためでしょう。閑話休題。)ある時点で、RPG %INT() 関数の場合と同様に、計算中に数式から小数点以下の数字を切り捨てる必要がありました。当然、CL にはそのような関数はありません。しかし CHGVAR コマンドは生まれながらにして、その結果が小数点以下の桁がないフィールドに移動する場合に、数式から少数点以下の桁を切り捨てる能力を備えています。だから、それこそ、私が行っていたことでした。

また CEE API を使用して剰余計算をしていました。それらの数学関数はパック 10 進数には対応していないため、モジュールのすべての数値変数は整数 (*INT または *UINT) でした。

テスト中、1 つずつ数字を走り読みするプログラムを作成し、どのようになるのか確認しました。ある一点で、プログラムは広範囲の数字を通り過ぎて、次のレベルへとジャンプしました。この動作は開始点に関係なく発生し、プログラムは常に同じ相対スポットでジャンプしました。デバッグした結果、式の結果の小数点部分が 0.5 以上の場合、プログラムは結果を次の桁へと四捨五入していたのです。

「おー」私は思いました、「これは話が違う」と。(まあ、実際私の頭に最初に浮かんだのは、「W」で始まるおなじみの 3 文字のインターネット頭字語でしたが。)ちょっとしたテストを行い、VAR パラメーターのフィールドが整数 (*INT または *UINT) の場合、プログラムは数学的四捨五入を行っていたことを検証できました。フィールドがゼロ位置を持つ小数部 (*DEC) の場合、プログラムはその値に関係なく小数点部分を切り捨てるでしょう。

たとえば、121 を 33 で割ると、結果は 3.6666666 です。この値を整数フィールドに移動すると、4 に四捨五入されます。小数点フィールドに移動すると、3 に切り捨てられます。しかし、121 を 35 で割ると、結果は 3.4571428 です。この値を移動すると、整数フィールドに移動しようが、パック 10 進数フィールドに移動しようが、最終的に値は常に 3 になります。

それでも整数フィールドを使用して、正しい結果を得たかったため、CHGVAR コマンドを変更し、式全体から 0.5 を除算してから結果を VAR パラメーターのフィールドに移動するようにしました。私のプログラムは正常に動作していました。しかし、この新機能に関する記事を思い出せなかったため、まずは IBM インフォメーション・センターに当たってみました。CHGVAR コマンドと CL の数式について解説した記事すべて読みましたが、この動作については何も見つかりませんでした。

次に IBM にサービス要求を開き、私の発見をテストするため多少の CL プログラムを提供しました。IBM の人に、彼らのシステムでそれを実行し、私の気が狂っていないことを確認してもらうよう依頼しました。そして、これがバグなのか、文書化されていない機能なのかを説明してくれるよう頼みました。IBM は即座に私の結果を確認しました。そして数週間やりとりがあった後、予想もしていなかったことを告げられました。

私が期待していたことは、整数を CL に追加したときに発生した内容を IBM が何らかの理由で文書化できなかったことを告白してくれるというものでした。期待していなかったことは、それが機能でありバグであると告げられたことでした。思わず古い Razzles のコマーシャルを思い出してしまいました (「最初はキャンディーで、そのうちガムに…」)。5.3 で整数サポートを CL に追加した開発者は、新しい整数フィールドの四捨五入をサポートするよう故意に CHGVAR コマンドを変更したのだから、それは機能です。ところが、動作は %BINARY() 関数など整数も処理する他の CL 部分、または文字フィールドの 10 進数を数値に変換するプロセスと一貫性がないのだから、それはバグです。

この動作を自分で確認する場合は、ご使用のシステムで図2 の CL プログラムをコンパイルしてください。CLP または CLLE のいずれでコンパイルしてもかまいません。

このプログラムは、小数点部分が 0.5 (3.6666666) 以上の数字と式、また小数点部分が 0.5 (3.4571428) 未満の数字と式を使用して、CHGVAR コマンドの文字変換機能と数式機能をテストしています。これらの値は、次の 3 種類の数値フィールドでテストされています。

  • %BINARY() 関数を使用して文字フィールド (&RESULTC) に保存された 4 バイト整数
  • 4 バイト整数フィールド (&RESULTI)
  • 小数点以下の桁数ゼロの 5 桁のパック 10 進数フィールド (&RESULTP)

次のようなテストを行いました。

  • 小数点部分が 0.5 以上の場合 (C >= 0.5) の文字変換
  • 小数点部分が 0.5 未満の場合 (C < 0.5) の文字変換
  • 小数点部分が 0.5 以上の場合(E >= 0.5) の数式
  • 小数点部分が 0.5 未満の場合 (E < 0.5) の数式

プログラムを実行すると、次のメッセージがジョブ・ログに記録されているはずです。

  • E >= 0.5: Integer and packed do not match!
  • E >= 0.5: %BIN and integer do not match!

機能またはバグのプログラム一時修正 (PTF) は次のとおりです。

  • 7.1: 5770SS1-SI44398
  • 6.1: 5761SS1-SI44397
  • 5.4: 5722SS1-SI44395
  • 5.3: なし (機能またはバグが最初に現れた 5.3 の PTF はありません。このリリースはすでにサポート停止になっているためです。)

PTF 適用後、修正を有効にするために CL モジュールおよびプログラムを再コンパイルする必要があります。コンパイルの前に、整数を伴う既存の式でバグがすでに回避されていないことを確認します。そうした回避は、式全体から 0.5 を除算することで達成できるケースが多いです。こうした回避に遭遇した場合は、単にそれらを削除してください。CL を再コンパイルすれば大丈夫なはずです。

ページトップ

ボタン