完全なコードが表示されない場合、問題はおそらくどこかfloat
のループで反復変数としてを使用していることが原因だと思います。for
float
次のプログラムを例として使用すると、を反復変数として直接 使用しようとすると、浮動小数点の精度がループのどこかで台無しになることを再現できます。
float duration = 10f;
for(float elapsed = 0.0f; elapsed <= duration; elapsed = elapsed + 0.1f) {
Console.WriteLine(2.0f - elapsed / (duration / 2.0f));
}
Console.ReadLine();
このプログラムの出力は次のとおりです。
2
1.98
1.96
1.94
1.92
1.9
1.88
1.86
1.84
1.82
1.8
1.78
1.76
1.74
1.72
1.7
1.68
1.66
1.64
1.62
1.6
1.58
1.56
1.54
1.52
1.5
1.48
1.46
1.44
1.42
1.4
1.38
1.36
1.34
1.32
1.3
1.28
1.26
1.24
1.22
1.2
1.18
1.16
1.14
1.12
1.1
1.08
1.06
1.04
1.02
1
0.9800005
0.9600005
0.9400005
0.9200006
0.9000006
0.8800006
0.8600006
0.8400006
0.8200006
0.8000007
0.7800007
0.7600007
0.7400007
0.7200007
0.7000008
0.6800008
0.6600008
0.6400008
0.6200008
0.6000009
0.5800009
0.5600009
0.5400009
0.5200009
0.500001
0.480001
0.460001
0.440001
0.420001
0.400001
0.3800011
0.360001
0.3400009
0.3200008
0.3000008
0.2800007
0.2600006
0.2400005
0.2200005
0.2000004
0.1800003
0.1600002
0.1400001
0.1200001
0.1
0.07999992
0.05999985
0.03999977
0.01999969
精度のシュートの約半分が終了していることがわかります。これは、反復変数自体の精度が台無しになっているためです。
2番目の例では、integer
代わりに反復変数としてを使用しinteger
、各反復内の計算に合わせて単純にスケーリングします。これにより、反復変数がすべて厄介になるのを防ぎます。
float duration = 10f;
float offset_scale = 10.0f;
for (int elapsed = 0; elapsed <= (duration * offset_scale); elapsed++) {
Console.WriteLine(2.0f - (elapsed / offset_scale) / (duration / 2.0f));
}
Console.ReadLine();
このプログラムの出力は次のとおりです。
2
1.98
1.96
1.94
1.92
1.9
1.88
1.86
1.84
1.82
1.8
1.78
1.76
1.74
1.72
1.7
1.68
1.66
1.64
1.62
1.6
1.58
1.56
1.54
1.52
1.5
1.48
1.46
1.44
1.42
1.4
1.38
1.36
1.34
1.32
1.3
1.28
1.26
1.24
1.22
1.2
1.18
1.16
1.14
1.12
1.1
1.08
1.06
1.04
1.02
1
0.98
0.96
0.94
0.92
0.9
0.88
0.86
0.84
0.82
0.8
0.78
0.76
0.74
0.72
0.7
0.68
0.66
0.64
0.62
0.6
0.58
0.56
0.54
0.52
0.5
0.48
0.46
0.44
0.42
0.4
0.38
0.36
0.34
0.32
0.3
0.28
0.26
0.24
0.22
0.2
0.18
0.16
0.14
0.12
0.1
0.08
0.06
0.04
0.02
0
精度が狂うことはなく、結果は0になります。