You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

uint64_t类型使用减法运算符结果异常的原因排查

问题原因与解决方案:uint64_t连续减法结果不符合预期

这问题的核心是浮点数的精度限制在搞鬼,咱们来一步步理清楚:

为什么结果不对?

你代码里用的1e19、8e18这类数值是double类型的浮点数字面量,而你操作的val是uint64_t(64位无符号整数)。

double类型的二进制尾数只有53位,这意味着它只能精确表示小于2^53(约9.007e15)的整数。当数值超过这个范围后,double就没办法精准存储所有整数了——低位的二进制位会被丢弃,只保留高位的近似值。

你的初始值0xFFFFFFFFFFFFFFFFULL是18446744073709551615,远大于2^53。当你执行val -= 1e19时,编译器会先把val转换成double类型(此时已经丢失了部分低位精度),再和1e19(本身也是不精确的浮点数)做减法,最后把结果转回uint64_t,自然就会出现末尾数字不符合预期的情况。

怎么解决?

改用64位无符号整数字面量来代替浮点数,这样所有运算都会是精确的整数运算,不会有精度损失。只需要把1e19这类写法换成对应的整数,并加上ULL后缀(表示这是无符号长整型,对应uint64_t):

修正后的代码

#include <stdio.h>
#include <stdint.h>

int main() {
    uint64_t val = 0xFFFFFFFFFFFFFFFFULL; // 0xFF FF FF FF FF FF FF FF ULL = 8 bytes
    printf("[ 0] %ju\n", val);
    printf("[ 1] %ju\n", val -= 10000000000000000000ULL);
    printf("[ 2] %ju\n", val -= 8000000000000000000ULL);
    printf("[ 3] %ju\n", val -= 400000000000000000ULL);
    printf("[ 4] %ju\n", val -= 40000000000000000ULL);
    printf("[ 5] %ju\n", val -= 6000000000000000ULL);
    printf("[ 6] %ju\n", val -= 700000000000000ULL);
    return 0;
}

编译运行

还是用你原来的命令:

gcc -Wall main.c -o main.exe && ./main.exe

运行后就能得到符合预期的结果,所有运算都是精确的64位整数操作,不会再出现末尾数字错误的问题。

内容的提问来源于stack exchange,提问作者Marek Czechyra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 10:57:46