NormalizeDoubleによるMT4での数値の丸め方 - ページ 4

 
Dmitry Fedoseev:
これは0.6だから、0.5は不正行為によってしか得られないからだ。

double v1 = 1.1234567;

任意の数値に「v1」が挿入されていれば、「i=2」に正しく丸められたことを示す。

 
lilita bogachkova:

任意の数値に「v1」を挿入すると、「i=2」まではすべて正しく丸められることがわかる。

i = 2 以降は間違い?
 
Ihor Herasko:

1桁だけ正規化する場合は、0、1、2、3、4→0、5、6、7、8、9→1という単純なもので、1桁だけ正規化する場合は、0、1、2、3、4→0、5、6、7、8、9→1という単純なものです。

2桁を正規化する場合、0〜49→0、50〜99→1というように2桁の数字が考慮される。結局のところ、1.49という数字を整数に丸めなければならない場合、1に対する利用可能な100分の49の距離に対して、100分の51である2を本当に得なければならないのだろうか?

3桁、4桁などでも同じです。

しかし、1.45は2に切り上げられるが、それは以前に1度高い精度で正規化されていた場合のみである。

void OnStart()
  {
   for(int i=7;i>=0;i--)
     {
      double v1 = 1.4545454;
      double v2 = NormalizeDouble(v1,i+1);

      v1=NormalizeDouble(v1,i);
      v2=NormalizeDouble(v2,i);
      Print("v1 = ",i," = ",DoubleToString(v1,7),", v2 = ",i," = ",DoubleToString(v2,7));
     }
     Print("---");
  }


v1 = 0 = 1.0000000, v2 = 0 = 2.0000000

v1 = 1 = 1.5000000, v2 = 1 = 1.5000000

v1 = 2 = 1.4500000、v2 = 2 = 1.4600000

v1 = 3 = 1.4550000, v2 = 3 = 1.4550000

の計算で高い精度に正規化され、その後の計算で低い精度にこの数を正規化すると、単に低い精度にこの数を正規化した場合とは異なる結果になることが判明しました。


 
lilita bogachkova:

というのは、計算時に高い精度で正規化した数値を、その後の計算で低い精度で正規化すると、ただ低い精度で正規化した場合とは異なる結果になることがわかったからです。


以上、このような行為を「ズルい」と言います))数学は厳密な科学ですが、やはり理解した上で応用しなければなりません。2+3=5 だが、バケツ2+ニワトリ3なら5は成立しない ))
 

失礼ですが、どのようにして欲しい値を手に入れるのでしょうか?

推奨機能を使えば

- あるケースでは、正しく丸められた値が得られます
0.06-0.02=NormalizeDouble(0.03999999999,2) =0.04
割り算は近似的で、正規化が必要です。

- 2番目のケースでは、丸めも出てきますが、この場合は必要ありません
0.06-0.024= NormalizeDouble(0.036,2) =0.04
ここでは正規化(丸め)は必要ありません。

しかし、四捨五入ではなく、正規化するにはどうしたらいいのでしょうか?

 
Roman Starinskij:

失礼ですが、どのようにして欲しい値を手に入れるのでしょうか?

そのためには、「正しい価値観」とは何かを定式化することに意味があるのです))

推奨機能を使えば

- あるケースでは、正しく丸められた値が得られます。
0.06-0.02= NormalizeDouble(0.03999999999,2) =0.04と なります。
割り算は近似的に行われるので、正規化しないとできない。

- 2つ目のケースでは、丸めも発生しますが、このケースでは必要ありません
0.06-0.024= NormalizeDouble(0.036,2) =0.04と なります。
ここでは正規化(丸め)は必要ありません。

しかし、値を丸めるのではなく、きちんと正規化するにはどうしたらいいのでしょうか?

上の例では、正規化の「正しさ」を判断する何らかの直感的なアルゴリズムを使っていることがわかります。前者では無限小数、後者では有限小数である。実数を目的の形に変換するアルゴリズムを調整する。

最も簡単な方法は、事前に必要な精度を決めておくことです。

 
Ihor Herasko:

そのためには、単純に「正しい価値観」とは何かを定式化することに意味があります))

上記の例から、正規化の「必要性」を判断するために、何らかの直感的なアルゴリズムを使っていることがわかります。前者では無限小数、後者では有限小数である。実数を目的の形に変換するアルゴリズムを調整する。

最も簡単な方法は、必要な精度をあらかじめ決めておくことですが。


今まで電卓で出していた、同じ数字が出ればいいんです。:-)これが、あなたに必要な価値観です。
つまり、「0.06-0.02」では「0.04」、「0.06-0.024」では「0.036」となるわけだ。
 
Roman Starinskij:

電卓と同じ数値が出ればいいんです。:-)これが、あなたに必要な価値観です。
0.06-0.02」なら「0.04」、「0.06-0.024」なら「0.036」となるのです。
0.036(小数点以下3桁)を求める場合は、小数点以下2桁ではなく、小数点以下3桁で正規化する必要があります。
 
Dmitry Fedoseev:
0.036(小数点以下3桁)が必要な場合は、2ではなく3に正規化します。

3桁までが正規化されるはずと勘違いしていました。このようなことは可能でしょうか?

 
Roman Starinskij:

3桁までが正規化されるはずと勘違いしていました。そのようにうまくいくのでしょうか?

これがあなたのコードです。

0.06-0.024 = NormalizeDouble(0.036,2) = 0.04

2の代わりに3を入れると、0.036になります。

理由: