Logistic functionのような関数を使用すると、さらに良い解決策が得られる場合があります。
Double minAlt = 0.0;
Double maxAlt = 500000.0;
Int32 numberSteps = 1000;
Double boundary = +6.0;
for (Int32 step = 0; step < numberSteps; step++)
{
Double t = -boundary + 2.0 * boundary * step / (numberSteps - 1);
Double correction = 1.0 / (1.0 + Math.Exp(Math.Abs(boundary)));
Double value = 1.0 / (1.0 + Math.Exp(-t));
Double correctedValue = (value - correction) / (1.0 - 2.0 * correction);
Double curAlt = correctedValue * (maxAlt - minAlt) + minAlt;
}
現在の高度は明示的に計算されるため、あらゆる種類の精度関連エラーを導入する反復計算に頼る必要はありません。
関数形状を調整する方法については、サンプル コードを参照してください。
関数を表示するサンプル コンソール アプリケーションを次に示します。パラメータを少し操作して、動作の感触を掴むことができます。
using System;
namespace LogisticFunction
{
class Program
{
static void Main(string[] args)
{
Double minAlt = 5.0;
Double maxAlt = 95.0;
Int32 numberSteps = 60;
// Keep maxAlt and numberSteps small if you don't want a giant console window.
Console.SetWindowSize((Int32)maxAlt + 12, numberSteps + 1);
// Positive values produce ascending functions.
// Negative values produce descending functions.
// Values with smaller magnitude produce more linear functions.
// Values with larger magnitude produce more step like functions.
// Zero causes an error.
// Try for example +1.0, +6.0, +20.0 and -1.0, -6.0, -20.0
Double boundary = +6.0;
for (Int32 step = 0; step < numberSteps; step++)
{
Double t = -boundary + 2.0 * boundary * step / (numberSteps - 1);
Double correction = 1.0 / (1.0 + Math.Exp(Math.Abs(boundary)));
Double value = 1.0 / (1.0 + Math.Exp(-t));
Double correctedValue = (value - correction) / (1.0 - 2.0 * correction);
Double curAlt = correctedValue * (maxAlt - minAlt) + minAlt;
Console.WriteLine(String.Format("{0, 10:N4} {1}", curAlt, new String('#', (Int32)Math.Round(curAlt))));
}
Console.ReadLine();
}
}
}