3

次の while ループを最適化する方法についてアドバイスをお願いします。

double minor_interval   = 0.1;
double major_interval   = 1.0;

double start            = 0.0;
double finish           = 10.0;

printf("Start\r\n");

while (start < finish)
{
    printf("Minor interval: %.20f\r\n", start);

    double m = fmod(start, major_interval);
    printf("m: %.20f\r\n", m);

    if (m == 0)
        printf("At major interval: %.20f\r\n", start);

    start += minor_interval;
}

printf("Finished\r\n");

基本的に、ループ内のカウンタをマイナー インターバルでインクリメントしており、ループのたびにメジャー インターバルにあるかどうかを知りたいと考えています。これをミリ間隔で定規を描いていると想像してください。主要な間隔に到達するたびに、センチメートルを描きたいと思います。浮動小数点演算が不正確な場合、上記のループを変更して必要な機能を実装するにはどうすればよいですか? 公差を使用してモジュラスの結果を比較するさまざまな方法を試しましたが、運がありませんでした。マイナー インターバルとメジャー インターバルは任意の値、つまりマイナー = 0.4、メジャー = 1.6 (1/4 マイルの増分を描画するため) にできることに注意してください。

前もって感謝します。

4

3 に答える 3

6

intvariableに対する for ループを使用してこれを実装しますi。整数を使用すると、浮動小数点演算の制限による丸めの問題を回避できます。[すべてのコンピュータ科学者が浮動小数点演算について知っておくべきことを参照してください。]

からまでi実行し、に等しく設定します。の値は、最も近い int に丸めることによって見つけることができます。0iFinish-1timestart + i*minor_intervaliFinish(finish-start)/minor_interval

主軸の更新も同様の方法で処理できます。major_interval/minor_interval最も近いintに丸めますk。次に、k 回目の反復ごとに長軸マークを更新します。

コード的には、次のようになります。

double round(double r) {
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
...
int iFinish = round((finish-start)/minor_interval);
int k = round(major_interval/minor_interval);
for (int i=0; i<iFinish; i++)
{
    double time = start + i*minor_interval;
    bool isMajor = (i%k == 0);
    ...
}
于 2011-08-28T07:34:40.170 に答える
0

整数を使用して、ループをforループにします。また、数値の場合、これらのタイの性質が不正確であるため、float/doubleの==演算子は避ける必要があります。

したがって、ループの目的で倍精度浮動小数点数を整数に変換するには、次のようにします。

numIntervals = (int)((finish - start) / minor_intervals);
majIntervalsGap = numIntervals  / (int)((finish - start) / major_intervals);
double time = start;
for (int loop = 0;; loop < numIntervals; ++loop)
{
    bool isMajor = ((loop % majIntervalsGap) == 0);

    ... do you ourput here as you have the desired info for it
    time += minor_interval;
}
于 2011-08-28T08:29:56.797 に答える
0

公差の方法が機能しない理由は、保存された値が本来あるべき値よりもわずかに高い場合にのみ考慮されるためです。(例: 1 ではなく 1.0001 の場合。1 ではなく 0.999 の場合、メソッドは機能しません)

これを修正するには、期待値のいずれかの側で許容範囲内にあるかどうかを確認します。

したがって、代わりに:

if (m == 0)

使用する:

if (m < small_value || major_interval - m < small_value)

ここで、small_value は 1e-8 のようなものです。

于 2011-08-28T07:45:40.767 に答える