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

# はじめに

[こちらの記事](https://qiita.com/mylifewithviolin/items/d5d65042ca02477a680c)で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側だけの実装となりますが、[こちらの記事](https://qiita.com/mylifewithviolin/items/a9cd528ce1031a28f13c)でカスタマイズされたランタイムライブラリを使用しています。もしも本記事の内容をカスタマイズライブラリ含めてお試ししたい場合は辞書修正ツールで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
```mind:currency.src
通貨変数は　倍精度変数と　等価。
通貨型スケーリングは　文字列定数 "10000"。
通貨型スケーリング２は　文字列定数 "20000"。

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

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

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

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

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


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

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


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

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

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

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

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

    long2が　const0に　ｑ等しい
    ならば　"0000"を　表示し
    さもなければ
        long2が　const0より　ｑ小さい
        ならば long2に　const-1を　ｑ掛け long2に　入れ
        つぎに
        long2が const1　ｑ以上　かつ　long2が　const10より　ｑ小さい
        ならば 　"000"を　表示し
        さもなければ
            long2が const10　ｑ以上　かつ　long2が　const100より　ｑ小さい
            ならば 　"00"を　表示し
            さもなければ 　
                long2が const100　ｑ以上　かつ　long2が　const1000より　ｑ小さい
                ならば 　"0"を　表示し
                つぎに
            つぎに
        つぎに
        long2を   ＄＄倍精度表示し
    つぎに  
    。
```
実行結果のところで詳しく説明しますが、小数からキャストは２つ実装されていて、１つ目は浮動小数点型から倍精度変数型へのキャストを使ったバージョンと、２つ目は浮動小数点型をMind標準の小数形式文字列に変換して初期化するバージョンです。１つ目は浮動小数点型の小数点4桁目が丸められてしまう場合があることに気づいたため２つ目を実装しています。小数点4桁目が丸められてしまう挙動はCで実装したdobuleをlong longでキャストする際に起きているようでした。


# 動作チェック用ソースコードMindと実行結果
コンパイルは[こちらの記事](https://qiita.com/mylifewithviolin/items/a9cd528ce1031a28f13c)の浮動小数点変数から倍精度変数へキャストする単語追加版のfileライブラリでビルドします。
```
PS C:\developments\vscode\mind8\bin> mind ..\sample\checkcurr ..\lib\file
   
日本語プログラミング言語 Ｍｉｎｄ Version 8.07 for Windows
          Copyright(C) 1985 Scripts Lab. Inc.
コンパイル中 .. 終了
Coping.. c:\pmind\bin\mindex.exe --> ..\sample\checkcurr.exe
```

## 動作チェック用ソースコード（１）
まずはあたりさわりのない値で動作確認です。（と、当初思っていたのですが、小数からのキャストで問題発覚！結果の方で説明します。）
```mind:checkcurr.src
"../sample/currency.src"を　コンパイル。
    
メインとは
        curr1は　通貨変数
        curr2は　通貨変数
        int1は　変数
        long1は　倍精度変数
        float1は　小数変数
    "250.0001"で　ｃ文字列初期化し　curr1に　入れ
    "3.0003"で　ｃ文字列初期化し　curr2に　入れ
    123456を　int1に　入れ
    123456を　long1に　入れ
    12.3456を　float1に　入れ
    "ｃ文字列初期化 "を　表示し　curr1を　ｃ数値表示し　改行し
    "ｃ文字列初期化 "を　表示し　curr2を　ｃ数値表示し　改行し
    "32bit整数　　　"を　表示し　int1を　数値表示し　改行し
    "64bit整数　　　"を　表示し　long1を　＄＄倍精度表示し　改行し
    "64bit浮動小数　"を　表示し　float1を　4桁で　小数形式で表示し　改行し
    "ｃ一つ加え  　"を　表示し　curr1を　ｃ一つ加え　ｃ数値表示し　改行し
    "ｃ二つ加え  　"を　表示し　curr1を　ｃ二つ加え　ｃ数値表示し　改行し
    "ｃ一つ引き  　"を　表示し　curr1を　ｃ一つ引き　ｃ数値表示し　改行し
    "ｃ二つ引き 　 "を　表示し　curr1を　ｃ二つ引き　ｃ数値表示し　改行し
    "ｃ割り　　　　"を　表示し　curr1と　curr2を　ｃ割り　ｃ数値表示し　改行し
    "ｃ余り　　　　"を　表示し　curr1と　curr2を　ｃ余り　ｃ数値表示し　改行し
    "ｃキャスト　　"を　表示し　int1を　ｃキャストし　ｃ数値表示し　改行し
    "ｃ倍精度から　"を　表示し　long1を　ｃ倍精度からキャストし　ｃ数値表示し　改行し
    "ｃ小数から　　"を　表示し　float1を　ｃ小数からキャストし　ｃ数値表示し　改行し
    "ｃ小数から２　"を　表示し　float1を　ｃ小数からキャスト２し　ｃ数値表示し　改行し
    。
```

## 実行結果（１）
```
C:\developments\vscode\mind8\bin>..\sample\checkcurr
ｃ文字列初期化 250.0001
ｃ文字列初期化 3.0003
32bit整数　　　123456
64bit整数　　　123456
64bit浮動小数　12.3456
ｃ一つ加え  　251.0001
ｃ二つ加え  　252.0001
ｃ一つ引き  　249.0001
ｃ二つ引き 　 248.0001
ｃ割り　　　　83.0000
ｃ余り　　　　0.9752
ｃキャスト　　123456.0000
ｃ倍精度から　123456.0000
ｃ小数から　　12.3455
ｃ小数から２　12.3456
```
いちおう「ｃ小数からキャスト」を除いて想定値どおりです。:tada::tada::tada::tada:
「ｃ小数からキャスト」は12.0001、12.9999、12.3455、12.3457は値どおりでしたが、12.3456が12.3455になってしまいました。元の型は倍精度浮動小数点なので、12.34561と小数点5桁目になにか数字をおいておくとこの丸めはなくなったのですが、紛らわしいのでMind標準の小数形式で文字列かして文字列初期化する「ｃ小数からキャスト２」を追加しました。

## 動作チェック用ソースコード（２）
つづいてマイナス値での動作検証です。倍精度変数に32bit変数の範囲内の値を代入する場合、プラス値の場合は暗黙の型変換が正常動作しますが、マイナスの場合は符号の扱いが変わりますので、明示的な型変換が必要となることに注意します。
```mind:checkcurr.src
※～略～
    "-250.0001"で　ｃ文字列初期化し　curr1に　入れ
    "3.0003"で　ｃ文字列初期化し　curr2に　入れ
    -123456を　int1に　入れ
    -123456を ｑキャストし　long1に　入れ
    -12.3456を　float1に　入れ
※～略～
```

## 実行結果（２）
```
C:\developments\vscode\mind8\bin>..\sample\checkcurr
ｃ文字列初期化 -250.0001
ｃ文字列初期化 3.0003
32bit整数　　　-123456
64bit整数　　　-123456
64bit浮動小数　-12.3456
ｃ一つ加え  　-249.0001
ｃ二つ加え  　-248.0001
ｃ一つ引き  　-251.0001
ｃ二つ引き 　 -252.0001
ｃ割り　　　　-83.0000
ｃ余り　　　　0.9752
ｃキャスト　　-123456.0000
ｃ倍精度から　-123456.0000
ｃ小数から　　-12.3455
ｃ小数から２　-12.3456
```
今回のような比較的小さい値であれば「ｃ小数からキャスト２」はマイナス側も、設定したリテラルと同じ値に変換されました。:tada:
## 動作チェック用ソースコード（３）
せっかくなので正の値で大きめなのを狙ってみます。64bit符号付整数最大値に対して、3.0003が加算されてもオーバーフローしないようにその値分少ない値としています。浮動小数点につきましても同じ値としています。この変数からの初期化値に対しては加減算していませんが、浮動小数点を扱う際の誤差から最大値を初期設定するとキャストの際にオーバーフローチェックが作動するようでした。下図の条件はオーバーフローしない値設定です。（最大値-3.0003）
```mind:checkcurr.src
※～略～
    "922337203685474.5804"で　ｃ文字列初期化し　curr1に　入れ
    "3.0003"で　ｃ文字列初期化し　curr2に　入れ
    2147483647を　int1に　入れ
    "922337203685474"を ｑ文字列初期化し　long1に　入れ
    922337203685474.5804を　float1に　入れ
※～略～
```

## 実行結果（３）
```
C:\developments\vscode\mind8\bin>..\sample\checkcurr
ｃ文字列初期化 922337203685474.5804
ｃ文字列初期化 3.0003
32bit整数　　　2147483647
64bit整数　　　922337203685474
64bit浮動小数　922337203685474.6200
ｃ一つ加え  　922337203685475.5804
ｃ二つ加え  　922337203685476.5804
ｃ一つ引き  　922337203685473.5804
ｃ二つ引き 　 922337203685472.5804
ｃ割り　　　　307414993062518.0000
ｃ余り　　　　1.8250
ｃキャスト　　2147483647.0000
ｃ倍精度から　922337203685474.0000
ｃ小数から　　922337203685474.6112
ｃ小数から２　922337203685474.6200
```
今回のような比較的大きい値の場合、文字列変換を使った「ｃ小数からキャスト２」でも、設定したリテラルと若干異なる値に変換されました。このため、固定小数点型の最大値の小数形式表現の場合、オーバーフローが発生しました。

## 動作チェック用ソースコード（４）
続いてマイナスの値で大きめなのを狙ってみます。64bit符号付整数最小値に対して、3.0003が減算されてもオーバーフローしないようにその値分絶対値が少ない値としています。浮動小数点につきましても同じ値としています。
```mind:checkcurr.src
※～略～
   "-922337203685474.5805"で　ｃ文字列初期化し　curr1に　入れ
    "3.0003"で　ｃ文字列初期化し　curr2に　入れ
    -2147483648を　int1に　入れ
    "-922337203685474"を ｑ文字列初期化し　long1に　入れ
    -922337203685474.5805を　float1に　入れ
※～略～
```

## 実行結果（４）
```
C:\developments\vscode\mind8\bin>..\sample\checkcurr
ｃ文字列初期化 -922337203685474.5805
ｃ文字列初期化 3.0003
32bit整数　　　-2147483648
64bit整数　　　-922337203685474
64bit浮動小数　-922337203685474.6200
ｃ一つ加え  　-922337203685473.5805
ｃ二つ加え  　-922337203685472.5805
ｃ一つ引き  　-922337203685475.5805
ｃ二つ引き 　 -922337203685476.5805
ｃ割り　　　　-307414993062518.0000
ｃ余り　　　　-1.8251
ｃキャスト　　-2147483648.0000
ｃ倍精度から　-922337203685474.0000
ｃ小数から　　-922337203685474.6112
ｃ小数から２　-922337203685474.6200
```
正の場合と同様の結果となるようです。

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

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