C语言实数两种表示形式具体指什么?

99ANYc3cd6
预计阅读时长 13 分钟
位置: 首页 C语言 正文
  1. 浮点数
  2. 定点数

下面我们详细解释这两种形式。

在c语言中实数有两种表示形式
(图片来源网络,侵删)

浮点数

这是现代C语言中最常用、最标准的表示实数的方式,它的设计灵感来源于科学记数法,即一个数可以表示为 尾数 × 基数^指数 的形式。

a) 核心思想

计算机将实数的存储空间分为三个部分:

  • 符号位:1位,表示正负。
  • 指数位:若干位,表示小数点的位置,决定了数值的表示范围。
  • 尾数位:剩余的位,表示有效数字,决定了数值的精度。

这种“浮动”小数点的机制使得浮点数既能表示极大(如天体间的距离)也能表示极小(如原子质量)的数值,但精度会随着数值大小变化。

b) C语言中的类型

C语言通过三种关键字来提供不同精度的浮点类型:

在c语言中实数有两种表示形式
(图片来源网络,侵删)
类型 别名 通常占用字节 有效数字位数 精度说明
float 单精度浮点数 4 字节 (32位) 约 6-7 位 精度较低,适用于对精度要求不高的场景,如游戏中的坐标、图形学计算。
double 双精度浮点数 8 字节 (64位) 约 15-16 位 默认使用,精度足够高,适用于绝大多数科学计算、工程计算和金融计算。
long double 长双精度浮点数 8, 12, 或 16 字节 ≥ 15 位 提供比 double 更高的精度,具体实现依赖于编译器和平台。

c) 示例代码

#include <stdio.h>
int main() {
    float f = 3.1415926535f; // 注意 f 后缀,表示这是一个 float 常量
    double d = 3.141592653589793;
    printf("float f: %.10f\n", f); // 输出: float f: 3.1415925026
    printf("double d: %.15f\n", d); // 输出: double d: 3.141592653589793
    // 可以看到,float 在存储时丢失了精度,而 double 保留了更多有效数字。
    return 0;
}

d) 优点

  • 范围广:能表示非常大和非常小的数值。
  • 标准化:有IEEE 754等国际标准,保证了不同平台下计算结果的一致性。
  • 硬件支持:现代CPU都有专门的浮点运算单元,计算速度很快。

e) 缺点

  • 精度有限:由于存储空间有限,浮点数无法精确表示所有十进制小数(1 在二进制浮点数中是一个无限循环小数,只能近似存储),这会导致精度误差
  • 存在特殊值:如 NaN (Not a Number) 和 Infinity,需要小心处理。

定点数

定点数是一种更简单、更直接的表示方法,它不使用指数,而是预先约定好小数点的位置

a) 核心思想

一个定点数被看作一个整数,程序员需要自己记住或通过数据结构(如结构体)来跟踪小数点的位置,我们可以用一个32位的整数来表示金额,并约定小数点后有2位数字。

  • 例子:用 int 类型存储 12345,我们约定小数点后有2位,那么它实际代表的值是 45

b) C语言中的实现

C语言没有内置的定点数类型,实现定点数通常有两种方式:

  1. 使用整数类型模拟:直接使用 int, long, int64_t 等整数类型,程序员通过编程约定来管理小数点。
  2. 使用自定义结构体:将整数部分和小数部分封装在一个结构体中,这样更清晰,但效率较低。

c) 示例代码 (使用整数模拟)

#include <stdio.h>
#include <stdint.h> // 用于 int64_t
// 假设我们使用 int64_t,并约定小数点后有4位精度
typedef int64_t fixed_t;
// 将浮点数转换为定点数
#define FLOAT_TO_FIXED(f) ((fixed_t)((f) * 10000))
// 将定点数转换为浮点数
#define FIXED_TO_FLOAT(f) ((double)(f) / 10000.0)
// 定点数加法
fixed_t fixed_add(fixed_t a, fixed_t b) {
    return a + b;
}
int main() {
    fixed_t price = FLOAT_TO_FIXED(19.95); // 19.95 * 10000 = 199500
    fixed_t tax = FLOAT_TO_FIXED(1.25);   // 1.25 * 10000 = 12500
    fixed_t total_price = fixed_add(price, tax); // 199500 + 12500 = 212000
    double total_float = FIXED_TO_FLOAT(total_price); // 212000 / 10000.0 = 21.2
    printf("Price (fixed): %lld\n", price);      // 输出: Price (fixed): 199500
    printf("Tax (fixed): %lld\n", tax);        // 输出: Tax (fixed): 12500
    printf("Total (float): %.2f\n", total_float); // 输出: Total (float): 21.20
    return 0;
}

d) 优点

  • 精确表示:只要小数部分能被约定的基数(如10、100)整除,就可以精确表示,非常适合金融计算(如货币)。
  • 计算速度快:定点数的运算本质上是整数运算,在某些没有强大FPU的嵌入式系统中,比浮点数运算更快。
  • 可预测性:没有浮点数那样的舍入误差累积问题。

e) 缺点

  • 范围受限:由于没有指数,表示的范围远小于浮点数,容易发生溢出
  • 使用复杂:程序员需要手动处理小数点的转换和运算,容易出错。
  • 不通用:没有统一的硬件支持,所有运算都需要软件模拟(除非使用特殊的DSP指令)。

总结与对比

特性 浮点数 定点数
底层原理 科学记数法(符号、指数、尾数) 固定小数点位置
C语言支持 内置类型 (float, double, long double) 无内置类型,需用整数或结构体模拟
精度 有限精度,存在舍入误差 可精确表示特定小数(如0.1, 0.01)
数值范围 范围极广,从极小到极大 范围受限,容易溢出
运算速度 现代CPU上非常快(有FPU支持) 在无FPU的嵌入式系统中可能更快,否则较慢
主要用途 科学计算、图形学、机器学习、通用计算 金融计算(货币)、嵌入式系统、对精度要求苛刻的领域
编程复杂度 ,直接使用即可 ,需要手动管理小数点,容易出错

如何选择?

  • 优先选择 double:在绝大多数情况下,直接使用 double 是最佳选择,它提供了足够的精度和范围,并且性能优异。
  • 在特定场景下考虑定点数
    • 当你处理的业务数据必须精确(例如货币计算,不能有 1 + 0.2 != 0.3 的情况)。
    • 当你工作在资源受限的嵌入式系统,且该系统没有硬件浮点单元,而你的应用对性能要求很高。
    • 当你处理的数值范围固定且不会溢出,并且需要完全避免浮点数的舍入误差。

浮点数是C语言中表示实数的“标准武器”,而定点数则是一种在特定需求下(尤其是精度和性能权衡)的“特殊战术”

-- 展开阅读全文 --
头像
C语言如何实现十进制小数转二进制?
« 上一篇 02-05
dede数据库文件如何还原?
下一篇 » 02-05
取消
微信二维码
支付宝二维码

目录[+]