グーグルドライブ、リブレオフィス、エクセルでいろいろな銀行丸め(jis丸め)の式を検証してみた。結果、round系の区間交替型&重ね合わせ型が最優秀だった。int系の区間交替型&重ね合わせ型はシンプルで結構好きだが誤差が出てしまった。特異点型は思ったより悪くない。検証してないがround系で組めば少し改善するかも知れない。二重丸め型が最もダメだった。第二引き数を活用した式やintと併用した式は特に悪かった。
元数=$B8 (小数点以下の)桁数=$I$4 とする。
round系区間交替型 銀行丸め4c
CJ8= =if(MOD(ABS($B8)*10^$I$4,2)>=1,round($B8,$I$4),if(abs($B8)<=1/2/(10^$I$4),0,ROUNDUP($B8-sign($B8)*1/2/(10^$I$4),$I$4) ) )
round系重ね合わせ型 銀行丸め7
CK8= =if(abs($B8)<=1/2/10^$I$4,0,ROUNDUP($B8/2-sign($B8)*1/4/10^$I$4,$I$4)+rounddown($B8/2+sign($B8)/4/10^$I$4,$I$4) )
round系重ね合わせ型 銀行丸め7b
CL8= =if(abs($B8)<=1/2/10^$I$4,0,ROUNDUP($B8/2-sign($B8)*1/4/10^$I$4,$I$4)+round($B8/2-sign($B8)/4/10^$I$4,$I$4) )
検証方法
中心値xと(小数点以下の)桁数yと分割数zをセット(1件と数えた)にして、誤った値を目視でカウントしていく方法。誤差を探すための別列には「平均を使った統計的な数値」が良いと思ったが、優秀そうな式との差の絶対値の合計の10^y倍を表示した。優秀そうな式が合っていればそのまま誤差の式の個数になるから数えやすい。更に別列に誤差累計も表示したので計数途中でセルが移動しても元の位置が分かりやすい。(行の固定部分で計数した。押すと1増えるボタンを作れば効率アップだが今はそんな力はないw)
元の数はxより小さい方に106行、大きい方に107行。1行下に行くと1/10^y/z増える。
(x, y, z)=(0, 0, 20)の場合、元の数は-5.30~5.35。
元の数は関数ではなく値(マクロで入力するのが理想的か)の方が良さそうだが、様々な検証をするためには関数の手軽さは捨てがたい。誤差が累積しないようにrow()を元に計算した。元数由来の誤差はなるべく減らしたいが完璧は無理かも。(急ぐ時は「1行上のセル+間隔」とかよくやる)
具体的には B列(8~221行)= =(row()-114)*1/10^y/z+x 114行目が中心値
最初の9件 (0, 2, 2)(0, 3, 2)(1, 3, 20)(-1, 3, 20)(1, 2, 20)(-1, 2, 20)(0, 4, 20)(1, 4, 20)(-1, 4, 20) (個数が3桁を超えた物は計数が大変なので検証に含めずスルーしてしまったものもある)
(追記 番外編 グーグルで(0, 6, 2)が175個だった。二重丸め型4つが順に0個57個59個59個。)
追加の3件 (0, 6, 20)(1, 6, 20)(-1, 6, 20)
検証十分とは言えないがまあまあの結果は出せたと思う。
列の順は検証時と同じではなく種類別に並べ替えた。CD276:CP280は誤差の個数。なので「.0」は不要だが念のため表示しておいた。
|
CD |
CE |
CF |
CG |
CH |
CI |
CJ |
CK |
CL |
CM |
CN |
CO |
CP |
CQ |
CR |
CS |
CT |
273 |
int if mod |
round |
round |
int round |
int round |
int |
int if mod |
round round -up if mod他 |
int |
int |
round -down round -up他 |
round round -up if sign他 |
|
|
|
|
|
274 |
銀行丸 め式9 |
銀行 丸め1 |
銀行 丸め1b |
銀行 丸め1c |
銀行 丸め1d |
銀行 丸め4 |
銀行 丸め4b |
銀行 丸め4c |
銀行 丸め6 |
銀行 丸め6b |
銀行 丸め7 |
銀行 丸め7b |
|
|
|
|
|
275 |
特異点 連続型 |
二重 丸め奇 |
二重 丸め奇 |
二重 丸め奇 |
二重 丸め奇 |
区間 交替 |
区間 交替 |
区間 交替 |
重ね 合わせ |
重ね 合わせ |
重ね 合わせ |
重ね 合わせ |
|
|
|
|
|
276 |
14.0 |
8.0 |
74.0 |
68.0 |
68.0 |
2.0 |
2.0 |
0.0 |
2.0 |
2.0 |
0.0 |
0.0 |
240.0 |
小計 |
|
google |
|
277 |
12.0 |
8.0 |
36.0 |
36.0 |
36.0 |
0.0 |
0.0 |
0.0 |
0.0 |
0.0 |
0.0 |
0.0 |
128.0 |
小計 |
|
LibO3 |
|
278 |
2.0 |
6.0 |
8.0 |
6.0 |
6.0 |
0.0 |
0.0 |
0.0 |
0.0 |
0.0 |
0.0 |
0.0 |
28.0 |
小計 |
|
LibO7 |
|
279 |
14.0 |
8.0 |
77.0 |
70.0 |
70.0 |
2.0 |
2.0 |
0.0 |
2.0 |
2.0 |
0.0 |
0.0 |
247.0 |
小計 |
|
excel |
|
280 |
42.0 |
34.0 |
195.0 |
180.0 |
180.0 |
4.0 |
4.0 |
0.0 |
4.0 |
4.0 |
0.0 |
0.0 |
643.0 |
合計 |
|
|
|
LibO7は前9件がgoogleと一致していたので省略。LibO3は範囲コピーするだけで毎回ソフトが落ちた。エクセルでもエクセルが何度か落ちた。いくつか開きっぱなしだった仕事用ファイルも一緒に落ちて「修復」させられた。検証用のファイルを別途用意するのが正解と思う。
LibO3=LibreOfficePortable3.4.5
LibO7=LibreOfficePortable7.5.4
余談1
銀行丸め4bと6bは気に入ってた4と6で誤差が出てしまったから微修正して改善を期待した。結果は同数で改善なしだった。シンプルに書けるint系で誤差が出てしまったのはつくづく残念。
言い訳になるが(0, 6, 20)の中心±10行目の±0.0000005が元数の丸め結果が±0.000001の誤差だった(その値で同時に誤差だったのはマイナス側の
特異点型のみ)。しかし同じ元数である(0, 6, 2)の中心±1行目の±0.0000005が元数の丸め結果はちゃんと0になった。つまり元数の設定方法由来の誤差の可能性がある。
余談2
今回最優秀な式はround系で第二引き数を使った形だった。第二引き数を使わない形の方が精度が上がるのだろうか?後で検証するかも。
余談3
最初は誤った値のつもりで「誤値」という単語を使ったが一般的ではないらしいので「誤差」に変更した(少しは電波度を減らさないとw)。ちょっとニュアンスが変わってしまう気がするが間違いではないから問題ない。
元の頁(blogger)は2023.06.15 19:26公開 単純ミスなどは適宜修正済&修正予定