C++ 中的日志基础 2 精度错误
log base 2 precision error in c++
请解释以下给定代码的输出。对于这两种情况,我都得到了不同的 c 值,即,
情况 1:n 的值取自标准输入。情况2:n的值直接写在代码中。友情链接 : http://www.ideone.com/UjYFQd
#include <iostream>
#include <cstdio>
#include <math.h>
using namespace std;
int main()
{
int c;
int n;
scanf("%d", &n); //n = 64
c = (log(n) / log(2));
cout << c << endl; //OUTPUT = 5
n = 64;
c = (log(n) / log(2));
cout << c << endl; //OUTPUT = 6
return 0;
}
您可能会看到这一点,因为浮点数的存储方式:
double result = log(n) / log(2); // where you input n as 64
int c = (int)result; // this will truncate result. If result is 5.99999999999999, you will get 5
对值进行硬编码时,编译器将为您优化它:
double result = log(64) / log(2); // which is the same as 6 * log(2) / log(2)
int c = (int)result;
很可能会完全替换为:
int c = 6;
因为编译器会看到您正在使用一堆编译时常量将值存储在变量中(它将继续在编译时处理值)。
如果要获取操作的整数结果,则应使用 std::round
而不是仅强制转换为int
。
int c = std::round(log(n) / log(2));
计算log(n)/log(2)
,结果非常接近6,但略少。这就是浮点计算的工作方式:log(64) 和 log(2) 在二进制浮点中都没有无限精确的表示,因此您可以预期将一个除以另一个的结果与真正的数学值略有偏差。根据实现的不同,您可以期望获得 5 或 6。
在第二个计算中:
n = 64;
c = (log(n) / log(2));
分配给c
的值可以推断为编译时常量,并且可以由编译器计算。编译器在运行时在与程序不同的环境中执行计算,因此您可能会从编译时和运行时执行的计算中获得略有不同的结果。
例如,为 x86 生成代码的编译器可以选择使用使用 80 位浮点运算的 x87 浮点指令,而编译器本身使用标准的 64 位浮点运算来计算编译时常量。
检查编译器的汇编程序输出以确认这一点。使用 GCC 4.8,我从两次计算中都得到了 6
输出的差异可以用以下事实来解释:gcc
在常量情况下优化了对log
的调用,例如,在这种情况下:
n = 64;
c = (log(n) / log(2));
对log
的两个调用都是在编译时完成的,这些编译时计算可能会导致不同的结果。这记录在 gcc 手册的 GCC 提供的其他内置函数部分,其中说:
GCC 包括标准 C 库中许多函数的内置版本。以 _builtin 为前缀的版本始终被视为与 C 库函数具有相同的含义,即使您指定了 -fno 内置选项也是如此。(请参阅 C 方言选项)其中许多功能仅在某些情况下进行优化;如果它们在特定情况下未优化,则会发出对库函数的调用。
log
是具有内置版本的众多函数之一。如果我使用 -fno-builtin
构建所有对 log
的四个调用,但没有它,只会发出一个对log
的调用,您可以通过使用 -S
标志进行构建来检查这一点,该标志将输出gcc
生成的程序集。
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 主.cpp:18:20:错误:从"int*"转换为"int"会失去精度 [-fa
- 错误C++在Visual Studio 2019中使用numeric_limits的长双精度最小值/最大值
- 野牛/flex:计算器将双精度值解释为整数,所以我添加了 YYSTYPE 双精度 #define 但我有多个编译错误
- 为什么 2 个双精度值之间的差值计算错误?
- 提升多精度浮点数128:标准::exp错误:'no matching function for call'
- 为什么使用 int64_t 会产生错误的结果,而双精度则按预期进行简单的整数乘法
- CIN 双精度和不带空格的字符串会导致错误
- 标准库to_string(双精度)在 vs2015 中给出错误的值.有什么解决办法吗?
- C++错误:从“int*”转换为“int”会失去精度
- Opengl 精度转换错误编译错误 E0415
- 使用 gcc 编译时,PowerPC 上的长双精度错误
- 在发布版本中划分两个双精度的结果错误
- 由于C++中双精度类型的准确性而导致的错误
- C++ 中的日志基础 2 精度错误
- C++ 中的十进制精度错误
- visual C++使用字符串流进行字符串到双精度转换会产生精度错误
- 解决设置精度错误的方法
- c++浮点精度错误
- 类c++中的浮点和双精度错误