[英]Wrapping floats counter in C++
這個問題指的是這個問題,但也適用於浮點數。
簡而言之,如果 count 達到 min 或 max bound,它應該考慮到 step 值溢出的剩余部分(例如,如果 bounds 是0... 10.5
, value
是 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.