对于使用定点算法的泰勒级数计算,我需要最多6个小数位精度。我尝试了不同的定点格式来实现6位小数精度。
例如, 使用s16.15(左移15)格式,我得到2位小数精度.1符号位,16位整数位和15位小数位。
对于s8.23(左移23)格式,最多4个小数位,s4.27(左移27)格式的精度仍然相同。我原以为情况会好转。
以下是泰勒级数展开计算某个点a附近的自然对数。
所以q = x-a,x是1到2之间的用户输入。
<div>
<label class="required">Langues</label>
<div id="homebundle_personnel_langues" data-prototype="<div><label for="homebundle_personnel_langues___name__" class="required">__name__label__</label><input type="text" id="homebundle_personnel_langues___name__" name="homebundle_personnel[langues][__name__]" required="required" value="New Tag Placeholder" /></div>">
</div>
</div>
上面提到的代码片段用于C。
结果我需要:0.584963,但我得到的结果是:0.584949
如何实现更高的精确度?
答案 0 :(得分:2)
OP mul()
抛出太多精确度。
(x)>>13)*((y)>>13)
会立即丢弃x
和y
的最不重要的13位。
而是执行64位乘法
int32_t mul_better(int32_t x, int32_t y) {
int64_t mul = x;
mul *= y;
mul >>= 27;
// Code may want to detect overflow here (not shown)
return (int32_t) mul;
}
更好的是,在丢弃最低有效位之前将产品四舍五入到最近(与均匀相关)。简化是可能的。下面的详细代码,因为它是说明性的。
int32_t mul_better(int32_t x, int32_t y) {
int64_t mul = x;
mul *= y;
int32_t least = mul % ((int32_t)1 << 27);
mul /= (int32_t)1 << 27;
int carry = 0;
if (least >= 0) {
if (least > ((int32_t)1 << 26) carry = 1;
else if ((least == ((int32_t)1 << 26)) && (mul % 2)) carry = 1;
} else {
if (-least > ((int32_t)1 << 26) carry = -1;
else if ((-least == ((int32_t)1 << 26)) && (mul % 2)) carry = -1;
}
return (int32_t) (mul + carry);
}
int32_t mul(int32_t x, int32_t y) {
int64_t mul = x;
mul *= y;
return mul >> 27;
}
void foo(double x) {
int32_t q = (int32_t) (x * (1 << 27)); // **
int32_t taylor =
c0 + mul(q, (c1 - mul(q, (c2 + mul(q,
(c3 - mul(q, (c4 - mul(q, (c5 + mul(q, c6)))))))))));
printf("%f %f\n", x, taylor * 1.0 / (1 << 27));
}
int main(void) {
foo(0.303609);
}
输出
0.303609 0.584963
**也可以在这里舍入,而不是简单地将FP截断为整数。