LoginSignup
3
0

Mind8で通貨型(64bit整数の4桁スケーリング固定小数点型)の実装のつづき(currency.src)

Posted at

はじめに

こちらの記事で4桁スケーリング固定小数点型の通貨変数の四則演算を実装してみていますが、今回はその周辺の単語についても追加実装してみます。

通貨型変数とは

通貨型変数とは符号付き64bit整数(-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)として格納され、小数点の左側に 15 桁、右側に 4 桁の固定小数点を指定して 10,000 でスケーリングされて入出力します。実際は整数型ですが、見かけ上は、-922,337,203,685,477.5808 ~ 922,337,203,685,477.5807 の範囲が扱えるようにした固定小数点型変数です。

前提条件

Windows11 Pro 22H2
VSCode(Visual Studo Code) 1.86.1
Microsoft Visual C++ 2008 Express Edition
Mind Version 7.5 for Windows
Mind Version 8.07 for Windows

MindはMind8のバージョンのパスが構成されていることを前提とします。今回はMind8側だけの実装となりますが、こちらの記事でカスタマイズされたランタイムライブラリを使用しています。もしも本記事の内容をカスタマイズライブラリ含めてお試ししたい場合は辞書修正ツールでMind7のライセンスが必要となりますのでご注意ください。

VSCodeの拡張機能

C/C++ for Visual Studio Code 1.18.5 Microsoft
C/C++ Extension Pack 1.3.0 Microsoft

C/C++のデバッガはMind8のCカーネルアプリケーションをデバッグ実行するために使用しています。今回はMind側だけの実装となります。

お題のソースコード Mind

今回はメイン付きのテスト用アプリケーション部分とライブラリを分離して実装してみます。倍精度変数の定数宣言が使用できていないので、変数を初期化しているところは少しまわりくどく感じるかもしれません。

currency.src

currency.src
通貨変数は 倍精度変数と 等価。
通貨型スケーリングは 文字列定数 "10000"。
通貨型スケーリング2は 文字列定数 "20000"。

c加えは   q加えと 等価。
c引くは   q引くと 等価。
c等しいは q等しいと 等価。
c大きいは q大きいと 等価。
c小さいは q小さいと 等価。
c以上は   q以上と 等価。
c以下は   q以下と 等価。
c異なるは q異なると 等価。
c余りは   q余りと 等価。

c一つ加えとは
        scaleは 倍精度変数
    通貨型スケーリングを q文字列初期化し scaleに 入れ
    scaleを q加え
    。

c二つ加えとは
        scale2は 倍精度変数
    通貨型スケーリング2を q文字列初期化し scale2に 入れ
    scale2を q加え
    。
c一つ引きとは
        scaleは 倍精度変数
    通貨型スケーリングを q文字列初期化し scaleに 入れ
    scaleを q引き
    。
c二つ引きとは
        scale2は 倍精度変数
    通貨型スケーリング2を q文字列初期化し scale2に 入れ
    scale2を q引き
    。

c掛けとは
        scaleは 倍精度変数
    通貨型スケーリングを q文字列初期化し scaleに 入れ
    q掛け scaleを q割り
    。

c割りは 
        scaleは 倍精度変数
    通貨型スケーリングを q文字列初期化し scaleに 入れ
    q割り scaleを q掛け
    。


c文字列初期化とは
        初期化文字列は 文字列
        整数部文字列は 文字列
        小数部文字列は 文字列

    初期化文字列に 入れ
    初期化文字列から 4文字だけ 右側取り出し 小数部文字列に 入れ
    初期化文字列から 初期化文字列の 文字数から 5文字 引いて 取り出し 整数部文字列に 入れ
    整数部文字列と 小数部文字列を 合成し
    q文字列初期化し
    。


cキャストとは
        scaleは 倍精度変数
    通貨型スケーリングを q文字列初期化し scaleに 入れ
    qキャストし scaleを q掛け
    。

c倍精度からキャストとは
        scaleは 倍精度変数
    通貨型スケーリングを q文字列初期化し scaleに 入れ
    scaleを q掛け
    。

c小数からキャストとは 処理単語 小数入力
        float1は 小数変数
        f10000は 小数定数 10000.0
        long1は 倍精度変数
        long2は 倍精度変数
        scaleは 倍精度変数
    float1に 入れ
    通貨型スケーリングを q文字列初期化し scaleに 入れ
    float1に f10000を f掛け  q小数からキャストし long1に 入れ
    long1と scaleの q余り long2に 入れ
    long1と scaleを q割り long1に 入れ
    long1と scaleを q掛け long2を q加え
    。

c小数からキャスト2とは 処理単語 小数入力
    0桁と 4桁で 文字列変換・小数形式し
    c文字列初期化し 
    。

c数値表示とは
        long1は 倍精度変数
        long2は 倍精度変数
        scaleは 倍精度変数
        const-1は 倍精度変数
        const0は 倍精度変数
        const1は 倍精度変数
        const10は 倍精度変数
        const100は 倍精度変数
        const1000は 倍精度変数
    long1に 入れ
    通貨型スケーリングを q文字列初期化し scaleに 入れ
    -1を qキャストし const-1に 入れ
    0を qキャストし const0に 入れ
    1を qキャストし const1に 入れ
    10を qキャストし const10に 入れ
    100を qキャストし const100に 入れ
    1000を qキャストし const1000に 入れ
    long1と scaleの q余り long2に 入れ
    long1と scaleを q割り  $$倍精度表示し "."を 表示し 

    long2が const0に q等しい
    ならば "0000"を 表示し
    さもなければ
        long2が const0より q小さい
        ならば long2に const-1を q掛け long2に 入れ
        つぎに
        long2が const1 q以上 かつ long2が const10より q小さい
        ならば  "000"を 表示し
        さもなければ
            long2が const10 q以上 かつ long2が const100より q小さい
            ならば  "00"を 表示し
            さもなければ  
                long2が const100 q以上 かつ long2が const1000より q小さい
                ならば  "0"を 表示し
                つぎに
            つぎに
        つぎに
        long2を   $$倍精度表示し
    つぎに  
    。

実行結果のところで詳しく説明しますが、小数からキャストは2つ実装されていて、1つ目は浮動小数点型から倍精度変数型へのキャストを使ったバージョンと、2つ目は浮動小数点型をMind標準の小数形式文字列に変換して初期化するバージョンです。1つ目は浮動小数点型の小数点4桁目が丸められてしまう場合があることに気づいたため2つ目を実装しています。小数点4桁目が丸められてしまう挙動はCで実装したdobuleをlong longでキャストする際に起きているようでした。

動作チェック用ソースコードMindと実行結果

コンパイルはこちらの記事の浮動小数点変数から倍精度変数へキャストする単語追加版のfileライブラリでビルドします。

PS C:\developments\vscode\mind8\bin> mind ..\sample\checkcurr ..\lib\file
   
日本語プログラミング言語 Mind Version 8.07 for Windows
          Copyright(C) 1985 Scripts Lab. Inc.
コンパイル中 .. 終了
Coping.. c:\pmind\bin\mindex.exe --> ..\sample\checkcurr.exe

動作チェック用ソースコード(1)

まずはあたりさわりのない値で動作確認です。(と、当初思っていたのですが、小数からのキャストで問題発覚!結果の方で説明します。)

checkcurr.src
"../sample/currency.src"を コンパイル。
    
メインとは
        curr1は 通貨変数
        curr2は 通貨変数
        int1は 変数
        long1は 倍精度変数
        float1は 小数変数
    "250.0001"で c文字列初期化し curr1に 入れ
    "3.0003"で c文字列初期化し curr2に 入れ
    123456を int1に 入れ
    123456を long1に 入れ
    12.3456を float1に 入れ
    "c文字列初期化 "を 表示し curr1を c数値表示し 改行し
    "c文字列初期化 "を 表示し curr2を c数値表示し 改行し
    "32bit整数   "を 表示し int1を 数値表示し 改行し
    "64bit整数   "を 表示し long1を $$倍精度表示し 改行し
    "64bit浮動小数 "を 表示し float1を 4桁で 小数形式で表示し 改行し
    "c一つ加え   "を 表示し curr1を c一つ加え c数値表示し 改行し
    "c二つ加え   "を 表示し curr1を c二つ加え c数値表示し 改行し
    "c一つ引き   "を 表示し curr1を c一つ引き c数値表示し 改行し
    "c二つ引き   "を 表示し curr1を c二つ引き c数値表示し 改行し
    "c割り    "を 表示し curr1と curr2を c割り c数値表示し 改行し
    "c余り    "を 表示し curr1と curr2を c余り c数値表示し 改行し
    "cキャスト  "を 表示し int1を cキャストし c数値表示し 改行し
    "c倍精度から "を 表示し long1を c倍精度からキャストし c数値表示し 改行し
    "c小数から  "を 表示し float1を c小数からキャストし c数値表示し 改行し
    "c小数から2 "を 表示し float1を c小数からキャスト2し c数値表示し 改行し
    。

実行結果(1)

C:\developments\vscode\mind8\bin>..\sample\checkcurr
c文字列初期化 250.0001
c文字列初期化 3.0003
32bit整数   123456
64bit整数   123456
64bit浮動小数 12.3456
c一つ加え   251.0001
c二つ加え   252.0001
c一つ引き   249.0001
c二つ引き   248.0001
c割り    83.0000
c余り    0.9752
cキャスト  123456.0000
c倍精度から 123456.0000
c小数から  12.3455
c小数から2 12.3456

いちおう「c小数からキャスト」を除いて想定値どおりです。:tada::tada::tada::tada:
「c小数からキャスト」は12.0001、12.9999、12.3455、12.3457は値どおりでしたが、12.3456が12.3455になってしまいました。元の型は倍精度浮動小数点なので、12.34561と小数点5桁目になにか数字をおいておくとこの丸めはなくなったのですが、紛らわしいのでMind標準の小数形式で文字列かして文字列初期化する「c小数からキャスト2」を追加しました。

動作チェック用ソースコード(2)

つづいてマイナス値での動作検証です。倍精度変数に32bit変数の範囲内の値を代入する場合、プラス値の場合は暗黙の型変換が正常動作しますが、マイナスの場合は符号の扱いが変わりますので、明示的な型変換が必要となることに注意します。

checkcurr.src
※~略~
    "-250.0001"で c文字列初期化し curr1に 入れ
    "3.0003"で c文字列初期化し curr2に 入れ
    -123456を int1に 入れ
    -123456を qキャストし long1に 入れ
    -12.3456を float1に 入れ
※~略~

実行結果(2)

C:\developments\vscode\mind8\bin>..\sample\checkcurr
c文字列初期化 -250.0001
c文字列初期化 3.0003
32bit整数   -123456
64bit整数   -123456
64bit浮動小数 -12.3456
c一つ加え   -249.0001
c二つ加え   -248.0001
c一つ引き   -251.0001
c二つ引き   -252.0001
c割り    -83.0000
c余り    0.9752
cキャスト  -123456.0000
c倍精度から -123456.0000
c小数から  -12.3455
c小数から2 -12.3456

今回のような比較的小さい値であれば「c小数からキャスト2」はマイナス側も、設定したリテラルと同じ値に変換されました。:tada:

動作チェック用ソースコード(3)

せっかくなので正の値で大きめなのを狙ってみます。64bit符号付整数最大値に対して、3.0003が加算されてもオーバーフローしないようにその値分少ない値としています。浮動小数点につきましても同じ値としています。この変数からの初期化値に対しては加減算していませんが、浮動小数点を扱う際の誤差から最大値を初期設定するとキャストの際にオーバーフローチェックが作動するようでした。下図の条件はオーバーフローしない値設定です。(最大値-3.0003)

checkcurr.src
※~略~
    "922337203685474.5804"で c文字列初期化し curr1に 入れ
    "3.0003"で c文字列初期化し curr2に 入れ
    2147483647を int1に 入れ
    "922337203685474"を q文字列初期化し long1に 入れ
    922337203685474.5804を float1に 入れ
※~略~

実行結果(3)

C:\developments\vscode\mind8\bin>..\sample\checkcurr
c文字列初期化 922337203685474.5804
c文字列初期化 3.0003
32bit整数   2147483647
64bit整数   922337203685474
64bit浮動小数 922337203685474.6200
c一つ加え   922337203685475.5804
c二つ加え   922337203685476.5804
c一つ引き   922337203685473.5804
c二つ引き   922337203685472.5804
c割り    307414993062518.0000
c余り    1.8250
cキャスト  2147483647.0000
c倍精度から 922337203685474.0000
c小数から  922337203685474.6112
c小数から2 922337203685474.6200

今回のような比較的大きい値の場合、文字列変換を使った「c小数からキャスト2」でも、設定したリテラルと若干異なる値に変換されました。このため、固定小数点型の最大値の小数形式表現の場合、オーバーフローが発生しました。

動作チェック用ソースコード(4)

続いてマイナスの値で大きめなのを狙ってみます。64bit符号付整数最小値に対して、3.0003が減算されてもオーバーフローしないようにその値分絶対値が少ない値としています。浮動小数点につきましても同じ値としています。

checkcurr.src
※~略~
   "-922337203685474.5805"で c文字列初期化し curr1に 入れ
    "3.0003"で c文字列初期化し curr2に 入れ
    -2147483648を int1に 入れ
    "-922337203685474"を q文字列初期化し long1に 入れ
    -922337203685474.5805を float1に 入れ
※~略~

実行結果(4)

C:\developments\vscode\mind8\bin>..\sample\checkcurr
c文字列初期化 -922337203685474.5805
c文字列初期化 3.0003
32bit整数   -2147483648
64bit整数   -922337203685474
64bit浮動小数 -922337203685474.6200
c一つ加え   -922337203685473.5805
c二つ加え   -922337203685472.5805
c一つ引き   -922337203685475.5805
c二つ引き   -922337203685476.5805
c割り    -307414993062518.0000
c余り    -1.8251
cキャスト  -2147483648.0000
c倍精度から -922337203685474.0000
c小数から  -922337203685474.6112
c小数から2 -922337203685474.6200

正の場合と同様の結果となるようです。

おわりに

固定小数点型変数の処理単語もだいぶ出そろってはまいりましたが、このあたりを完備していくとなると、地道な長期にわたる作業が発生するものと推定されます。

属性指定が記述されていないのでMind正規単語のような型チェックが作動しないなど、重めの課題も残しつつとりあえずこのあたりでいったん単語整備の試みは終息に向かいたいと考えております。機会があればことの発端となったデータベースへの固定小数点対応というのに進行するかもしれません。

3
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0