簡體   English   中英

在 C++ 中包裝浮動計數器

[英]Wrapping floats counter in C++

這個問題指的是這個問題,但也適用於浮點數。

簡而言之,如果 count 達到 min 或 max bound,它應該考慮到 step 值溢出的剩余部分(例如,如果 bounds 是0... 10.5value是 3 並且step是 -7.5)。 此外,我們應該處理step值大於range值的情況。

范圍可以是任意的(負的、正的或混合的),但要考慮給定的斷言。

到目前為止,我有這種適用於整數的方法,但只要step是小數,就會給出錯誤的雙精度結果。

也不確定我們應該在比較雙打時在這里使用 epsilon 方法。

問題是如何為小數值正確實現此方法。

可運行代碼

#include <iostream>
#include <cmath>
#include <assert.h>

double
countInRange(const double step, const double value, const double minValue, const double maxValue)
{
    assert(minValue < maxValue);
    assert(value >= minValue && value <= maxValue);

    auto range = maxValue - minValue + 1;
    assert(fabs(step) <= range);

    auto result = value + step;

    if (result < minValue) {
        result += range;
    } else if (result > maxValue) {
        result -= range;
    }

    return result;
}

int main()
{
    double v = 358;

    printf("increment\n");

    for (int i = 0; i < 10; i++) {
        v = countInRange(0.5, v, 0, 359.5);
        printf("%f\n", v);
    }

    printf("decrement\n");

    v = 2;

    for (int i = 0; i < 10; i++) {
        v = countInRange(-0.5, v, 0, 359.5);
        printf("%f\n", v);
    }
}

編輯

所以我最終得到了兩種不同區間邏輯的方法,第一種取自 Superlokkus 的答案,它們可能無法涵蓋所有情況,但現在已經足夠了,感謝所有評論者

    /**
     * Wraps to minValue or maxValue plus step using half-open interval logic
     */
    double
    countInRange(const double step, const double value, const double minValue, const double maxValue)
    {
        assert(minValue < maxValue);
        assert(value >= minValue && value <= maxValue);

        auto range = maxValue - minValue + 1;

        assert(fabs(step) <= range);

        auto result = value + step;

        if (result < minValue) {
            result = maxValue - abs(minValue - result);
        } else if (result > maxValue) {
            result = minValue + (result - maxValue);
        }

        return result;
    }
    /**
     * Wraps to minValue or maxValue using closed interval logic
     */
    double
    countInRange(const int step, const double value, const double minValue, const double maxValue)
    {
        assert(minValue < maxValue);
        assert(value >= minValue && value <= maxValue);

        auto range = maxValue - minValue + 1;

        assert(abs(step) <= range);

        auto result = value + step;

        if (result < minValue) {
            result += range;
        } else if (result > maxValue) {
            result -= range;
        }

        return result;
    }

這是你的想法嗎?

#include <iostream>
#include <iomanip>
#include <stdexcept>
#include <cmath>

constexpr double
countInRange(const double step, const double value, const double minValue, const double maxValue)
{
    if (minValue > maxValue) {
        throw std::invalid_argument("minValue > maxValue");
    }

    auto result{value};
    result += step;

    if (result > maxValue) {
        result = minValue + (result - maxValue);
    } else if (result < minValue) {
        result = maxValue - std::abs(minValue - result);
    }

    return result;
}

int main()
{
    double v = 358;

   std::cout << std::showpoint <<"increment\n";

    for (int i = 0; i < 10; i++) {
        v = countInRange(0.5, v, 0, 359.5);
        std::cout << v << "\n";
    }

    std::cout << std::showpoint << "decrement\n";

    v = 2;

    for (int i = 0; i < 10; i++) {
        v = countInRange(-0.5, v, 0, 359.5);
        std::cout << v << "\n";
    }
}

Output:

增量358.500 359.000 359.500 0.500000 1.00000 1.50000 2.50000 2.50000 3.00000 3.00000 3.50000減少1.50000 1.50000 1.00000 0.500000 0.00000 0.00000 359.000 358.500 358.000 358.000 357.500 357.000 357.000 356.500 356.500 356.500 356.500 356.500

我刪除了斷言,因為它們不適合參數檢查,因為它們是不可移植的確定性遺漏,並且無法處理。 此外,由於您似乎打算編寫 C++,因此我將 output 的用法更正為最佳 C++ 實踐。

您可以在 function arguments 中使用指向浮點變量的指針。 這將避免在通過堆棧傳輸值時更正值。

這種方式看起來有點臟,但如果你想保存 arguments 的精度,它應該可以工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM