C 浮点精度异常和分辨率
尽管 C 中的浮点数广泛使用,但它们在精度方面表现出局限性。考虑以下代码片段:
<code class="cpp">double a = 0.3; std::cout.precision(20); std::cout << a << std::endl;
此代码输出 0.2999999999999999889,而不是预期的 0.3。出现这种差异的原因是变量 a 并未完全存储为 0.3 双精度浮点数,而是由于浮点值的有限表示而存储为它的近似值。
当出现更令人惊讶的行为时,会出现以下情况: a 被重复添加 50 次:
<code class="cpp">double a, b; a = 0.3; b = 0; for (char i = 1; i <= 50; i++) { b = b + a; }; std::cout.precision(20); std::cout << b << std::endl;
这段代码令人惊讶地输出 15.000000000000014211 而不是 15.0。这是因为每次加法都会累积近似误差,导致累积误差大于原始精度。
解决精度异常
要获得精确的结果,需要避免将输出精度设置为大于数字类型的可用数字至关重要。这可以使用 std::numeric_limits 类来实现:
<code class="cpp">#include <iostream> #include <limits> int main() { double a = 0.3; std::cout.precision(std::numeric_limits<double>::digits10); std::cout << a << std::endl; double b = 0; for (char i = 1; i <= 50; i++) { b = b + a; }; std::cout.precision(std::numeric_limits<double>::digits10); std::cout << b << std::endl; }</code>
此代码使用digits10成员函数将精度设置为双精度浮点数的最大可用位数,即15
浮点运算的局限性
虽然提供的解决方案最大限度地减少了精度误差,但重要的是要认识到浮点运算具有固有的局限性。如果一个循环涉及数千次迭代,即使精度设置适当,累积误差也可能变得很大。在这种情况下,替代数据类型,例如定点数或有理数,可能更适合维护精确值。
以上是为什么 C 浮点运算会产生意想不到的结果,我们如何减轻这些精度异常?的详细内容。更多信息请关注PHP中文网其他相关文章!