跳转至

精度问题

下表给出了常见类型的精度(有效数字)和值域信息:

类型 精度 值域
float \(7\) \(\pm 10^{38}\)
int \(9\) \([-2^{31},2^{31})\)
double \(15\) \(\pm 10^{308}\)
long long \(18\) \([-2^{63},2^{63})\)
long double \(18\) \(10^{4932}\)

*数据来源:NOI-Linux 2.0,std::numeric_limits<typename> 内的宏。

得出结论:

  • 如果存在负数,一定不要开 unsigned
  • 最好不使用 float
  • 在值域不超过 long long 的时候,推荐使用 long long
  • 如果答案的位数超过了 \(15\) 位,那么使用 double 会出现精度问题:累加时,double 类型的变量如果超过了 \(15\) 位,并且 += 了一些小于此时精度的数字,就会被直接忽略;
  • 精度上,long double 可以代替 long long 处理值域较大的情况。

第三条问题的实例代码:

#include<iostream>
using namespace std;

int main() {

  #ifdef test_ll
    long long a;
  #else
    double a;
  #endif

    a += 1e17;

    for(int i = 1; i <= 10000000; i++) {
        a += 1;
    }

    printf("%lld\n", (long long)a);

    return 0;
}
long long:
100000000010000000
double:
100000000000000000