C语言floating是什么?浮点数如何使用?

99ANYc3cd6
预计阅读时长 23 分钟
位置: 首页 C语言 正文

“Floating” 通常指的是 浮点数,这是一种用于表示带有小数部分的数字的数据类型,与只能表示整数的 int 类型不同,浮点数可以表示像 14-0.0015e10 这样的数值。

c语言floating
(图片来源网络,侵删)

在 C 语言中,处理浮点数主要涉及三种基本类型:floatdoublelong double


浮点数类型

float (单精度浮点数)

  • 大小: 通常为 4 个字节 (32 位)。
  • 精度: 提供 约 6-7 位有效数字。
  • 用途: 当对内存占用要求非常严格,且数值范围和精度要求不高时使用,在游戏开发中用于图形坐标,或者在嵌入式系统中。

double (双精度浮点数)

  • 大小: 通常为 8 个字节 (64 位)。
  • 精度: 提供 约 15-16 位有效数字。
  • 用途: 这是 C 语言中最常用的浮点类型,提供了很好的精度和范围的平衡,在大多数科学计算、金融计算等场景中,默认就使用 double

long double (长双精度浮点数)

  • 大小: 不固定,通常是 8 字节、12 字节或 16 字节 (64/80/128 位)。
  • 精度: 提供 至少和 double 一样多,通常是 18-19 位或更多有效数字。
  • 用途: 当需要比 double 更高精度时使用,例如在高精度的科学计算或金融建模中。

类型大小和精度检查

你可以使用 C 语言的 sizeof<float.h> 头文件中的宏来了解你当前系统上这些类型的具体信息。

#include <stdio.h>
#include <float.h> // 包含浮点数特性的宏
int main() {
    printf("float 的存储大小: %lu 字节\n", sizeof(float));
    printf("float 的最小正数: %E\n", FLT_MIN);
    printf("float 的最大正数: %E\n", FLT_MAX);
    printf("float 的精度 (小数位数): %d\n", FLT_DIG);
    printf("\n");
    printf("double 的存储大小: %lu 字节\n", sizeof(double));
    printf("double 的最小正数: %E\n", DBL_MIN);
    printf("double 的最大正数: %E\n", DBL_MAX);
    printf("double 的精度 (小数位数): %d\n", DBL_DIG);
    printf("\n");
    printf("long double 的存储大小: %lu 字节\n", sizeof(long double));
    printf("long double 的最小正数: %LE\n", LDBL_MIN);
    printf("long double 的最大正数: %LE\n", LDBL_MAX);
    printf("long double 的精度 (小数位数): %d\n", LDBL_DIG);
    return 0;
}

注意: FLT_MAX 等宏的值会因平台(32位/64位)和编译器而异。


浮点数常量

在 C 语言中,如何书写一个浮点数常量?

c语言floating
(图片来源网络,侵删)
  • 十进制形式: 14, -0.5, .99,
  • 科学计数法 (E-notation): 14e2 (表示 3.14 10² = 314), -1.5E-3 (表示 -1.5 10⁻³ = -0.0015)

默认类型:

  • 如果一个浮点数常量包含小数点 () 或指数部分 (eE),它的默认类型是 double
  • 如果你想强制使用 float 类型,可以在数字后面加上 fF 后缀,14f
  • 如果你想强制使用 long double 类型,可以在数字后面加上 lL 后缀,14L
float f = 3.14f; // f 是 float 类型
double d = 3.14; // d 是 double 类型 (默认)
long double ld = 3.14L; // ld 是 long double 类型

浮点数变量声明与初始化

与整数变量类似,使用 float, double, long double 关键字来声明变量。

float pi = 3.14159f;
double price = 19.99;
long double large_number = 123456789012345.0L;

浮点数运算

浮点数可以使用标准的算术运算符:, , , 。

特别注意:

c语言floating
(图片来源网络,侵删)
  • 除法: 两个整数相除会得到整数结果(小数部分被丢弃),但只要操作数中有一个是浮点数,就会执行浮点数除法。
#include <stdio.h>
int main() {
    int a = 5;
    int b = 2;
    float c = 5.0f;
    float d = 2.0f;
    // 整数除法,结果是小数部分被截断
    int int_division = a / b;
    printf("5 / 2 (整数) = %d\n", int_division); // 输出 2
    // 浮点数除法
    float float_division = c / d;
    printf("5.0 / 2.0 (浮点) = %f\n", float_division); // 输出 2.500000
    // 混合类型除法:整数和浮点数,结果会自动提升为浮点数
    float mixed_division = a / d;
    printf("5 / 2.0 (混合) = %f\n", mixed_division); // 输出 2.500000
    return 0;
}

标准库函数

C 标准库 <math.h> 提供了丰富的数学函数来处理浮点数。

函数 描述 示例
sqrt(x) 计算 x 的平方根 sqrt(16.0) -> 0
pow(x, y) 计算 x 的 y 次方 pow(2.0, 3.0) -> 0
sin(x), cos(x), tan(x) 三角函数 (x 为弧度) sin(3.14159 / 2.0) -> ~1.0
log(x), log10(x) 自然对数和常用对数 log(10.0) -> ~2.302
fabs(x) 计算 x 的绝对值 fabs(-3.14) -> 14
ceil(x) 向上取整 (不小于 x 的最小整数) ceil(3.14) -> 0
floor(x) 向下取整 (不大于 x 的最大整数) floor(3.99) -> 0
#include <stdio.h>
#include <math.h> // 必须包含 math.h
int main() {
    double num = 16.0;
    double result = sqrt(num);
    printf("The square root of %.2f is %.2f\n", num, result); // 输出 4.00
    double angle = M_PI / 2; // M_PI 是 math.h 中定义的 π 值
    printf("sin(PI/2) = %f\n", sin(angle)); // 输出 ~1.000000
    return 0;
}

编译注意: 在 Linux/macOS 上使用 <math.h> 时,可能需要链接数学库,编译命令通常为 gcc your_program.c -o your_program -lm,在 Windows (如 MinGW) 中通常不需要。


关键问题:精度与误差

这是理解浮点数最重要的一点。

浮点数在计算机中不是精确存储的,而是用一种叫做 IEEE 754 的标准进行近似表示。 这会导致一些意想不到的结果。

问题 1: 精度有限

float 只有 6-7 位有效数字,如果你试图存储一个超过这个精度的数,它会被舍入。

float f = 123456789.0f;
printf("f = %.10f\n", f); // 可能输出 123456792.0000000000,最后几位不准确

问题 2: 误差累积

由于每次运算都可能引入微小的舍入误差,多次运算后误差会累积。

问题 3: 比较浮点数

永远不要使用 或 来精确比较两个浮点数是否相等! 因为微小的误差会导致比较失败。

正确的方法是使用一个很小的“容忍度”(epsilon)来判断两个浮点数是否“足够接近”。

#include <stdio.h>
#include <math.h>
// 判断两个浮点数是否“相等”
int are_floats_equal(double a, double b, double epsilon) {
    // 如果差的绝对值小于一个极小的数,就认为它们相等
    return fabs(a - b) < epsilon;
}
int main() {
    double a = 0.1 + 0.2;
    double b = 0.3;
    // 错误的比较方式
    if (a == b) {
        printf("a 和 b 精确相等\n"); // 这行代码很可能不会执行
    } else {
        printf("a 和 b 不精确相等 (a=%.20f, b=%.20f)\n", a, b); // 会输出
    }
    // 正确的比较方式
    double epsilon = 1e-9; // 一个很小的容忍度
    if (are_floats_equal(a, b, epsilon)) {
        printf("使用容忍度,a 和 b 被认为是相等的\n");
    } else {
        printf("使用容忍度,a 和 b 仍然不相等\n");
    }
    return 0;
}

输出示例:

a 和 b 不精确相等 (a=0.30000000000000004441, b=0.29999999999999998890)
使用容忍度,a 和 b 被认为是相等的

输入输出

使用 printfscanf 来处理浮点数的输入输出。

格式说明符 类型 示例
%f floatdouble (默认6位小数) printf("%f", 3.14159); -> 141590
%lf double (用于 scanfdouble 变量) scanf("%lf", &my_double);
%Lf long double (用于 scanflong double 变量) scanf("%Lf", &my_ldouble);
%.2f 保留2位小数 printf("%.2f", 3.14159); -> 14
%e 科学计数法 printf("%e", 1234.56); -> 234560e+03

重要提示:

  • printf 中,%f%lf 对于 double 类型变量效果是一样的。
  • scanf 中,必须使用 %lf 来读取 double 类型的变量,如果你错误地使用 %f,在 64 位系统上可能会导致未定义行为或读取错误,对于 floatscanf 使用 %f;对于 long double,使用 %Lf
#include <stdio.h>
int main() {
    double d;
    float f;
    printf("请输入一个 double 类型的数字: ");
    scanf("%lf", &d); // 正确:使用 %lf
    printf("请输入一个 float 类型的数字: ");
    scanf("%f", &f); // 正确:使用 %f
    printf("你输入的 double 是: %.2f\n", d);
    printf("你输入的 float 是: %.2f\n", f);
    return 0;
}
特性 描述
类型 float (低精度), double (高精度, 常用), long double (最高精度)
常量 14f (float), 14 (double, 默认), 14L (long double)
运算 , , , ,注意混合类型运算时的自动类型提升。
库函数 <math.h> 提供了 sqrt, pow, sin, fabs 等大量数学函数。
核心问题 精度有限和误差,不要用 比较浮点数,应使用容忍度方法。
I/O printf%f/%e/%gscanf%lf (double) / %f (float) / %Lf (long double)。
-- 展开阅读全文 --
头像
织梦猫数据库配置文件在哪?
« 上一篇 04-18
织梦如何调用视频缩略图?
下一篇 » 04-19

相关文章

取消
微信二维码
支付宝二维码

目录[+]