【C】原码和补码以及环形坐标取模算法

一切数字在计算机底层都是以补码的形式存储和计算,补码天然是无符号的。但为了人们方便数学计算,利用计算机数据溢出绕尾的特性,提出了有符号数,也就是原码。补码层面的计算也是符合数学逻辑,比如unsigned int 和 int计算,都先转成unsigned int计算,结果是unsigned int类型,和你都当成有符号类型去计算,结果是一样的。属于是数学统一下的一体两面。

以有符号单字节为例,无符号原码补码相同:

原码 5(0000 0101)的补码就是 5(0000 0101)

原码-5(1000 0101)的补码就是251(1111 1011)

正数的补码和原码相同

负数符号位不变,其余取反加1,就是补码。补码符号位不变,其余取反加1又变成原码。

负数的补码也可以通过"0加"获得,0等于256,0+(-5) = 256 - 5 = 251,模型如下图:

在C语言的公式计算中,可以先不考虑有符号无符号,单纯以数学逻辑去计算,最后看结果,中间只要注意算出的数会不会因为整型提升丢失符号位即可。https://kdocs.cn/l/cgXXFjtyTtfa

补充:

0-(-5) = 256 - 251 = 5,可以通过"0减"的方式算一个负数的绝对值。

模运算补充:

数学语境中的除运算(/)和模运算(%)是除法带余数和取整,规则上和Python中的运算是一样的,但是Python有(//)用于取整除。C语言中只有除运算(/)和模运算(%)是取整除和求余数。

被除数 = 商 × 除数 + 余数(记为:a = q × b + r),a / b = q 余 r。

商的符号由a和b决定,同号为正,异号为负。

Python算法上余数符号和除数(M)一致。C语言算法上余数符号和被除数(N)一致。

两者运算规则上的核心差异:python的商向下取整,C语言的商向0取整。

例子:

Python:-10 / 3 = -4 余 2,-10 = 3 * -4 + 2,因为-10 / 3等于-3.几,向下取整到-4。

C:-10 / 3 = -3 余 -1,-10 = 3 * -3 + -1,商向0取整到-3。

Python:10 / -3 = -4 余 -2,10 = -3 * -4 + -2

C:10 / -3 = -3 余 1,10 = -3 * -3 + 1

Python:-10 / -3 = 3 余 -1,-10 = -3 * 3 + -1,因为-10 / -3等于3.几,向下取整到3。

C:-10 / -3 = 3 余 -1,-10 = -3 * 3 + -1,因为-10 / -3等于3.几,向0取整到3。

Python:10 / 3 = 3 余 1,10 = 3 * 3 + 1

C:10 / 3 = 3 余 1,10 = 3 * 3 + 1

Python:-3 / 1000 = -1 余 997,-3 = 1000 * -1 + 997,因为-3 / 1000等于-0.几,向下取整到-1。

C:-3 / 1000 = 0 余 -3,-3 = 1000 * 0 + -3,商向0取整到0。

Python中商为正数时和C语言中是一样的,但是商小于等于0就不一样,故在C语言中当M是正值,N是负值的时候一定要用公式(N % M + M) % M,此时的结果和Python是一致的。模运算的本质就是把N拉到-M+1, M-1的范围内。且余数符号和除数一致,当M为正数,则余数范围0, M-1

补充:

数据在0, M-1的范围变化,总共有M个数据。从S点写LEN个数据到E点,E点是干净未处理的。

  • 有两个点S和E,从S加LEN到E,计算E,本质算法是E = (S + LEN) >= M ? ((S + LEN) - M) : (S + LEN);

对应取模算法:E = (S + LEN) % M,(S + LEN)是正值,直接%就行。

  • 有两个点S和E,从S减LEN到E,计算E,本质算法是E = (S - LEN) < 0 ? ((S - LEN) + M) : (S - LEN);

对应取模算法:E = (S - LEN + M) % M,(S - LEN + M)是正值,直接%就行。

  • 有两个点S和E,从S加LEN到E,计算LEN,本质算法是LEN = (E - S) >= 0 ? (E - S) : ((E - S) + M);

对应取模算法:LEN = ((E - S) % M + M) % M,(E - S)可能是负值,直接%的商也是负值,所以套用公式。

上述是数组类,LEN = 3是包含索引0在内。

如果是定时器节拍类,举例:实时时间R,之前时间C,超时时间D。LEN = 3是包含索引3在内,如下图。但两者本质上是一样的,只不过物理内容所在一个偏左一个偏右。

补充:上述"数据在0, M-1"的例子中,M是正数,"S - LEN"或"E - S"的绝对值不大于M:

  • "E = (S + LEN) % M"简化成"E = (S + LEN) % M";
  • "E = (S - LEN + M) % M"简化成"E = (S - LEN + M) % M",算"上N条"用法;
  • "LEN = ((E - S) % M + M) % M"简化成"LEN = (E - S + M) % M";
  • https://www.kdocs.cn/l/cp1DT0sq6ltW,见20240709,如果M是特殊的2的幂次数(整型变量的最大值+1),计算时则无需求余数,变量具有1个天然的模或者回绕点。
相关推荐
hPw0eKIqD2 小时前
C++ 模板参数推导问题小记(非推导上下文)
开发语言·c++
临床数据科学和人工智能兴趣组3 小时前
要使用 R Markdown,首先需要安装 R 和 RStudio,接着安装 rmarkdown 包
开发语言·数据挖掘·数据分析·r语言·r语言-4.2.1
普通攻击往后拉3 小时前
Leetcode 206. 反转链表
算法·leetcode·链表
Nebula嵌入式3 小时前
【C语言】09-深入解析main函数
linux·c语言·开发语言·嵌入式
@syh.3 小时前
【贪心】矩阵消除游戏
算法·游戏·矩阵
可编程芯片开发4 小时前
基于零极点配置的PID控制系统simulink建模与仿真
算法
徐小夕4 小时前
开源!我用SQLite + DuckDB打造了一款可视化AI问数平台
前端·算法·github
Hrain-AI5 小时前
2026 企业 AI 智能体平台横评:8 大主流平台 7 维度实测对比
人工智能·算法·机器学习
神罚天下ET5 小时前
c# ACME client (补充)
开发语言·c#