為有限值v0,v1并且值r在[0, 1]范圍內,將所述值v計算為以下,總是屬于[v0, v1]范圍,或者它可以是(略)外,由于舍入誤差?
double v0; // Finite
double v1; // Finite
double r; // In [0, 1]
double v = v0 * r v1 * (1.0 - r);
if (v0 <= v1)
assert(v0 <= v && v <= v1);
else
assert(v1 <= v && v <= v0);
uj5u.com熱心網友回復:
是的,可以。下面是一個例子:
#include <assert.h>
int main() {
double v0 = 2.670088631008241e-307;
double v1 = 2.6700889402193536e-307;
double r = 0.9999999999232185;
double v = v0 * r v1 * (1.0 - r);
if (v0 <= v1)
assert(v0 <= v && v <= v1);
else
assert(v1 <= v && v <= v0);
return 0;
}
這產生:
Assertion failed: (v0 <= v && v <= v1), function main, file b.cpp, line 12.
v在這種情況下計算的值是:
2.67009e-307
uj5u.com熱心網友回復:
各種評論和答案提供了v可能超出范圍的示例。
一個候選修復是往返r確定r并1.0 - r加起來為 1.0。
r = 1.0 - r;
r = 1.0 - r;
v = v0 * r v1 * (1.0 - r);
到目前為止,我一直無法通過 OP 的范圍測驗。
唉,@alias用這個技巧提供了一些失敗的案例。
問題是,部分產品v0 * r,并v1 * (1.0 - r)和它們的總和可能會舍都在一個方向創造外之[v0 ... v1]范圍。
第二備用(需要更多的測驗):計算v 遠離從v0,v1邊緣。
double dv = v1 - v0;
if (r < 0.5) {
v = v1 - dv*r;
} else {
double rn = 1.0 - r; // No error expected here.
v = v0 dv*rn;
}
現在任何時間四舍五入都反對將答案限制在[v0 ... v1]范圍內,它主要影響范圍的中間而不是末端。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/357610.html
