美文网首页
计算机中 float, double 的表示与计算

计算机中 float, double 的表示与计算

作者: 找不到工作 | 来源:发表于2021-02-28 08:46 被阅读0次

在某次面试中被问到,发现自己并不能解释清楚这个看似基础的问题。

浮点数如何表示

根据 IEEE.754 标准,我们用以下公式来表示 floatdouble

(-1)^{\rm sign} \times 2^{\rm exponent} \times (1 + {\rm fraction})

各变量的 bits 数如下:

type sign exponent fraction
float 1 8 23
double 1 11 52

但是每个区域的表示并不是简单的二进制直接转换,以表示 0.15625 为例。

float in bits
  • 首先我们 sign 是 0, 表示正数
  • exponent 是 -127 + \sum\limits_{i=23}^{30} b_{i} 2^{(i-23)} = -3
  • fraction 是 \sum\limits_{i=0}^{23} b_{i}2^{-(23-i)}= 2^{-2} = 0.25

因此,结果是
1 \times 2^{-3} \times (1 + 0.25) = 0.15625

exponent 的表示需要减去127。

fraction 的表示类似于二进制的小数定义(以 2 为底)。比如,十进制里的 0.11 实质上是 1 \times 10^{-1} + 1 \times 10^{-2} = 0.11。二进制里则应该是 1 \times 2^{-1} + 1 \times 2^{-2} = 0.75

浮点数精度

知道浮点数表示方法后,精度就是 fraction 部分外加符号位能表示的精度,即:

\log_{10}{2^{24}} = 7.225

例如:

  • 比 1 小的最大数字
0 01111110 11111111111111111111111 = 3f7f ffff 

1 − 2^{−24} ≈ 0.999999940395355225

  • 1
0 01111111 00000000000000000000000 = 3f80 0000
  • 比 1 大的最小数字
0 01111111 00000000000000000000001 = 3f80 0001

1 + 2^{−23} ≈ 1.00000011920928955

整型和浮点型运算速度

曾经自己想当然认为浮点型运算比整形慢,实验发现并不一定:

#include <iostream>
#include <chrono>

template<typename T>
void calculate(T x, T y, int count) {
  while (count != 0) {
    T a = x + y;
    T b = x - y;
    T c = x * y;
    T d = x / y;

    --count;
  }
}

int main(int argc, char const *argv[]) {
  const auto t1 = std::chrono::steady_clock::now();

  int count = std::numeric_limits<int>::max() / 2;

  calculate(2, 3, count);

  const auto t2 = std::chrono::steady_clock::now();

  calculate(1.3, 1.5, count);

  const auto t3 = std::chrono::steady_clock::now();

  std::cout << "int calculation: " <<
    std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count()
    << "us" << std::endl;

  std::cout << "float calculation: " <<
    std::chrono::duration_cast<std::chrono::microseconds>(t3 - t2).count()
    << "us" << std::endl;

  return 0;
}

结果是:

int calculation: 2879312us
float calculation: 1974401us

所以这个结论不成立。

为何 GPU 更擅长计算浮点数

cpu设计的目的其实更偏向高速的通用计算,既包括逻辑运算又包括数学运算。因此设计成功能齐全,但是运算核心较少。现在主流 CPU 只有 4 核。

gpu设计的目的是图形加速,也就是对每个像素点(非常多)进行简单的并行运算。因此设计成结构简单,但是运算核心非常多。例如,GTX1080系列显卡有 2560 个核心。

参考资料

  1. Single-precision floating-point format

  2. 格物致知-Floating Point

相关文章

  • 计算机中 float, double 的表示与计算

    在某次面试中被问到,发现自己并不能解释清楚这个看似基础的问题。 浮点数如何表示 根据 IEEE.754 标准,我们...

  • java基础---------数组与可变个数形参

    一、重点知识 double float小数在计算机中计算取得的都是近似值,所以存在精度问题 增强for循环专门用...

  • 关于BigDecimal

    我们都知道,在java中浮点数由double与float表示,他们在计算的时候会出现精度问题,比如 我们期望得到的...

  • Java语言中:float、double在内存中存储方式

    java语言中,float类型数字在计算机中用4个字节(32位)来存储。double类型占用8个字节(64位)。 ...

  • C 浮点数

    浮点数存储带来的问题 问题背景 计算机中浮点数(float或double类型)都有精度范围,对于超出精度范围的浮点...

  • mysql8 数据类型 float double decimal

    float数值类型用于表示单精度浮点数值,而double数值类型用于表示双精度浮点数值,float和double都...

  • 常见对象BigDecimal的概述

    BigDecimal的概述 由于在运算的时候,float类型和double很容易丢失精度,所以为了能精确表示,计算...

  • [java 基础]BigDecimal

    场景说明 在进行金额表示、金额计算时,不能使用double,float,要使用对精度支持更好的BigDecimal...

  • iOS中常用的数学函数

    每一个函数都有对应计算float / double / long double 的函数,这里只列出double类型...

  • 提示60-61

    第60条:如果需要精确的答案,请避免使用float和double float和double类型主要是为了科学计算和...

网友评论

      本文标题:计算机中 float, double 的表示与计算

      本文链接:https://www.haomeiwen.com/subject/rqowfltx.html