《C语言深度剖析》第二章 符号详解 p2(完结) C语言从入门到入土(进阶篇)(二)

简介: 本章节文章是作者通过观看《C语言深度剖析》等各种资料总结的精华,基础部分省略了不少,是为了让大家能够更加深入了解C语言的魅力!因为为了避免与之前的文章发生赘述,所以就直接讲作者认为的精华部分哈!现在正文开始!

2.1.3 -∞取整

84.png

#include <stdio.h>
#include <math.h> //因为使用了floor函数,需要添加该头文件
#include <windows.h>
int main()
{
//本质是向-∞取整,注意输出格式要不然看不到结果
printf("%.1f\n", floor(-2.9)); //-3
printf("%.1f\n", floor(-2.1)); //-3
printf("%.1f\n", floor(2.9)); //2
printf("%.1f\n", floor(2.1)); //2
system("pause");
return 0;
}

85.png


2.1.4 +∞取整

#include <stdio.h>
#include <math.h>
#include <windows.h>
int main()
{
//本质是向+∞取整,注意输出格式要不然看不到结果
printf("%.1f\n", ceil(-2.9)); //-2
printf("%.1f\n", ceil(-2.1)); //-2
printf("%.1f\n", ceil(2.9)); //3
printf("%.1f\n", ceil(2.1)); //3
system("pause");
return 0;
}

86.png

2.1.5 四舍五入

#include <stdio.h>
#include <math.h>
#include <windows.h>
int main()
{
//本质是四舍五入
printf("%.1f\n", round(2.1));
printf("%.1f\n", round(2.9));
printf("%.1f\n", round(-2.1));
printf("%.1f\n", round(-2.9));
system("pause");
return 0;
}

结论:浮点数(整数/整数),是有很多的取整方式的。

PS:C默认向0取整。


2.2 聊聊取模

取模概念:

如果 a 和 d 是两个自然数, d 非零,可以证明存在两个唯一的整数 q 和 r ,满足 a = q * d + r 且 0 ≤ r < d 。其中, q被称为商,r 被称为余数。


我们平时都是用的正数的取模,所以并没有发现什么问题,但是想一想,我们如果遇到负数的取模呢?

1

#include <stdio.h>
#include <windows.h>
int main ()
{
int a = 10 ;
int d = 3 ;
printf ( "%d\n" , a % d ); // 结果是 1
// 因为: a=10,d=3,q=3,r=1 0<=r<d(3)
// 所以: a = q*d+r -> 10=3*3+1
system ( "pause" );
return 0 ;
}

2

#include <stdio.h>
#include <windows.h>
int main ()
{
int a = - 10 ;
int d = 3 ;
//printf("%d\n", a/d); //C 语言中是 -3 ,很好理解
printf ( "%d\n" , a % d );
system ( "pause" );
return 0 ;
} 

87.png

但是2在python中我们发现是2?

结论:很显然,上面关于取模的定义,并不能满足语言上的取模运算


因为在 C 中,现在 - 10 % 3 出现了负数,根据定义:满足 a = q * d + r 且 0 ≤ r < d , C 语言中的余数,是不满足定义的, 因为,r < 0 了。

故,大家对取模有了一个修订版的定义:

如果 a 和 d 是两个自然数, d 非零,可以证明存在两个唯一的整数 q 和 r ,满足 a = q * d + r , q 为整数,且 0 ≤ | r | < | d | 。其中, q 被称为商, r 被称为余数。

有了这个新的定义,那么 C 中或者 Python 中的 “ 取模 ” ,就都能解释了。

解释 C : - 10 = ( - 3 ) * 3 + ( - 1 )

解释 Python : - 10 = ( ? ) * 3 + 2 , 其中,可以推到出来 , '?' 必须是-4 ( 后面验证 ). 即 - 10 = (

- 4 ) * 3 + 2 ,才能满足定义。

所以,在不同语言,同一个计算表达式,负数 “ 取模 ” 结果是不同的。我们可以称之为分别叫做正余数 和 负余数


2.2.2 是什么决定了这种现象

由上面的例子可以看出,具体余数r的大小,本质是取决于商q的。

而商,又取决谁呢?取决于除法计算的时候,取整规则。

简单说,要先算商,再算余数,而商的取法前面说了4种,这就要看编译器。


2.2.3 取余和取模一样吗?

这两个并不能严格等价 ( 虽然大部分情况差不多 ) 取余或者取模,都应该要算出商,然后才能得出余数。

本质 1 取整:

取余:尽可能让商,进行向0取整。

取模:尽可能让商,向-∞方向取整。

故:

C中%,本质其实是取余。

Python 中 % ,本质其实是取模。

理解链:

对任何一个大于 0 的数, 对其进行0向取整和-∞取整 ,取整方向是一致的。故取模等价于取余

对任何一个小于 0 的数, 对其进行0向取整和-∞取整 ,取整方向是相反的。故取模不等价于取余

同符号数据相除,得到的商,一定是正数(正数 vs 正整数),即大于 0 !

故,在对其商进行取整的时候,取模等价于取余。

本质 2 符号:

参与取余的两个数据,如果同符号,取模等价于取余



2.2.4 如果参与运算的数据,不同符号呢?


#include <stdio.h>
#include <windows.h>
int main()
{
printf("%d\n", -10 / 3); //结果:-3
printf("%d\n\n", -10 % 3); //结果:-1 为什么? -10=(-3)*3+(-1)
printf("%d\n", 10 / -3); //结果:-3
printf("%d\n\n", 10 % -3); //结果:1 为什么?10=(-3)*(-3)+1
system("pause");
return 0;
}

明显结论:如果不同符号,余数的求法,参考之前定义。而余数符号,与被除数相同()。

但是:


88.png


好像不是这样的,为什么呢?

重新看看定义:

如果 a 和 d 是两个自然数, d 非零,可以证明存在两个唯一的整数 q 和 r ,满足 a = q * d + r , q 为整数,且 0 ≤ | r | < | d | 。其中, q 被称为商, r 被称为余数。

a = q * d + r 变换成 r = a - q * d 变换成 r = a + ( - q * d )

对于: x = y + z ,这样的表达式, x 的符号 与 | y | 、 | z | 中大的数据一致。

而 r = a + ( - q * d ) 中, | a | 和 |- q * d | 的绝对值谁大,取决于商 q 的取整方式。

c 是向 0 取整的,也就是 q 本身的绝对值是减小的。

如:

- 10 / 3 =- 3.333 . 33 向 0 取整 - 3. a =- 10 | 10 | , - q * d =- ( - 3 ) * 3 = 9 | 9 |

10 /- 3 =- 3.333 . 33 向 0 取整 - 3. a = 10 | 10 | , - q * d =- ( - 3 ) * ( - 3 ) =- 9 | 9 |

绝对值都变小了

python 是向 - ∞ 取整的,也就是 q 本身的绝对值是增大的。

- 10 / 3 =- 3.333 . 33 '//' 向 - ∞ 取整 - 4. a =- 10 | 10 | , - q * d =- ( - 4 ) * 3 = 12 | 12 |

10 /- 3 =-- 3.333 . 33 '//' 向 - ∞ 取整 - 4. a = 10 | 10 | , - q * d =- ( - 4 ) * ( - 3 ) =- 12 | 12 |

绝对值都变大了

结论:如果参与取余的两个数据符号不同,在 C 语言中 ( 或者其他采用向 0 取整的语言如: C ++ , Java ) ,余数符号,与被除数相同。


2.2.5 总结

浮点数(或者整数相除),是有很多的取整方式的。

如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r , q 为整数,且0 ≤ |r| < |d|。其中,q 被称为商,r 被称为余数。

在不同语言,同一个计算表达式,“取模”结果是不同的。我们可以称之为分别叫做正余数 和 负余数。

具体余数r的大小,本质是取决于商q的。而商,又取决于除法计算的时候,取整规则。

取余vs取模: 取余尽可能让商,进行向0取整。取模尽可能让商,向-∞方向取整。

参与取余的两个数据,如果同符号,取模等价于取余。

如果参与取余的两个数据符号不同,在C语言中(或者其他采用向0取整的语言如:C++,Java),余数符号,与被除数相同。(因为采用的向0取整)


今天的内容就到这里了哈!!!

要是认为作者有一点帮助你的话!

就来一个点赞加关注吧!!!当然订阅是更是求之不得!

最后的最后谢谢大家的观看!!!

你们的支持是作者写作的最大动力!!!

下期见哈!!!

相关文章
|
1月前
|
存储 安全 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
|
1月前
|
存储 编译器 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
|
1月前
|
存储 C语言 C++
C语言------------指针笔试题目深度剖析
C语言------------指针笔试题目深度剖析
19 1
|
1月前
|
存储 小程序 C语言
【深度剖析数据在内存中的存储】C语言
【深度剖析数据在内存中的存储】C语言
|
1月前
|
存储 机器学习/深度学习 自然语言处理
【进阶C语言】编译与链接、预处理符号详解
【进阶C语言】编译与链接、预处理符号详解
24 0
|
1月前
|
存储 小程序 C语言
【C语言进阶】深度剖析数据在内存中的存储
【C语言进阶】深度剖析数据在内存中的存储
|
3月前
|
C语言
C语言陷阱——无符号数和有符号数的大小比较
C语言陷阱——无符号数和有符号数的大小比较
|
3月前
|
C语言
【C语言】C语言中的符号重载
【C语言】C语言中的符号重载
65 0
|
13天前
|
程序员 C语言
C语言库函数 — 内存函数(含模拟实现内存函数)
C语言库函数 — 内存函数(含模拟实现内存函数)
24 0
|
24天前
|
编译器 C语言 C++
【C语言】memset()函数(内存块初始化函数)
【C语言】memset()函数(内存块初始化函数)
26 0