当前位置:网站首页>In depth understanding of pre post + +, -- and negative modulus
In depth understanding of pre post + +, -- and negative modulus
2022-07-25 05:13:00 【Australopithecus northerner】
List of articles
Preface
This article mainly understands some pre post ++、- - Rules of use , First use ? How to use it first ; If there is no receiver , How is this first used and embodied ; We can understand the modulo operation of positive integers , Then think more deeply , How do negative numbers perform modulo operations ?
Next , I will discuss the above issues with you .
One 、++、- - First use ?
Before you know it , We may look at a little compilation to understand ;
1、 The difference between assigning initial value and assignment
First , Let's answer a question first , Whether the initial value and assignment are the same ?
…
Strictly speaking, it is different , But we often confuse these two concepts in our daily use , How is it different ? Let's understand it by assembly ;
int main()
{
int a = 10;// This is called the initial value
int b = 20;
b = a;// This is called assignment
return 0;
}

This is the assembly fragment corresponding to this code ;
Next , From the perspective of compilation , Explain it. , Why is the initial value assigned different from the assignment ;
In fact, from the perspective of compilation , We understand that assigning an initial value does not need to go through a register , Put data directly into the open space , This also shows that assigning initial values actually completes two things :1、 Open up space .2、 Assign values to the space .
Then let's take a look at assignment : Through the assembly instructions, we can see ,1、 Assignment does not need to open up space .2、 Assignment cannot be completed directly , It must be done through registers ;
The above is the difference between assigning initial value and assigning value ;
To sum up :
Assignment cannot be done directly , It must be done through registers ; But assigning initial value does not need register , It can be done directly ;
2、++、- -
Next, let's return to the theme ;
Test code :
int main()
{
int a = 4;
int b = 2;
b = a++;
return 0;
}
This code , You can see it at a glance b The value of becomes 4,a The value of becomes 5;
How to become ? Use it first and then add it ,a First use , That is, to b, And then add up ; You get the above results ;
This is a rough understanding , Next, let's understand the situation of the receiver from the perspective of assembly ;
This is the assembly corresponding to the above code ; Let me explain next ;
( First of all, increase by yourself , Reuse , The same is true )
Now let's talk about , Without receiving and releasing , Use this first ( Or how post use is embodied ;)
Test code :
int main()
{
int a = 1;
a++;
return 0;
}

The corresponding assembly language ;
We can see from assembly language , Without the receiver , First use ( Or post use does not exist , No one will receive , Naturally, it is not used first ( Or assembly instructions used later , After the direct self increase , Just write it back to memory )
Empathy ++a The same is true ;
The overall effect is similar to a++ It's the same ;
To sum up :
For pre post ++、- - Come on , If there is a receiving party , Will execute first use ( Or post use operation ), For those without a receiver , It will directly increase itself ( Or self reducing ), No unnecessary operations , At the same time, the front ++、- - And post ++、- - Can achieve the same effect ;
3、“ classic ” error
Let's have a look first , The following code :
int main()
{
int a = 1;
int b = 1;
b = (++a) + (++a) + (++a);
printf("%d\n",b);
return 0;
}
You can guess , This running result :
The answer is that this code has no definite result , Under different compilers , The results are different ;
stay VS2019 in :
stay Dev In the environment :
On mobile phone :
Why does this happen , Next, we will start from the perspective of compilation (VS2019 In the environment ) To understand :
The reasons for the above results , Mainly due to , Compilers for various platforms , The above assembly code is interpreted in different ways ,( It can also be considered that the code itself is not rigorous , The way to calculate is not the only ), about VS2019 Come on , What he thinks is to first ++ After execution , In the a The value of is written back to memory , In execution + Method operation ; But some compilers , It may be done first 1、2 step , Writing to memory , Read into the register , In execution 3 step , Then I didn't reset a The value of is written into memory again , then , Then add , And that leads to this , In memory a Value , It's always the last value , The value in the register is the value after self increment , But it is not written back to memory , It will cause the mixed use of the last value and the refreshed value , It will result in different final running results ;
To sum up :
In our daily study and work , We should avoid writing such ambiguous code , Reduce output bug The probability and cost ;
Two 、 Negative modulo ?
In us C In language learning .% Operators are often used , It's also widely used ;
But if we pay enough attention , We'll find out , We met % operation , It seems that they are all aimed at positive numbers ;
For negative numbers % We don't seem to know so much about computation ;
Then let's have a detailed look ;
1、 Rounding method
Before going into the subject formally , We need to learn about : The way of rounding :
int a=3.14;
stay C We all know in language , The way to round is , Give up the decimal part , Take the integral part directly , Such as the above code ,a=3;
Is there only one rounding method ?
Of course not ! There is diversity in the world , Moreover, C Language ;
A、 towards 0 integer
What do you mean , It means :
Sketch Map :
When we round a decimal , We should try our best to 0 Round the direction of ;
What do you mean ? for instance :
-3.79 integer , Namely -3;
-3.1 integer , Namely -3;
3.9 integer , Namely 3;
Now I can probably understand ;
This rounding method , Just ask us to get close 0 Of , And an integer close to our decimal ;
B、 Rounding negative infinity
This rounding method is also well understood :
Sketch Map :
Take a chestnut :
-3.79 integer , Namely -4;
-3.1 integer , Namely -4;
3.9 integer , Namely 3;
Now I can probably understand ;
This rounding method , It requires us to take something close to negative infinity , And an integer close to our decimal ;
C、 Rounding to positive infinity
This is easy to understand :
Sketch Map :
Take a chestnut :
-3.79 integer , Namely -3;
-3.1 integer , Namely -3;
3.9 integer , Namely 4;
Now I can probably understand ;
This rounding method , It requires us to take the one close to positive infinity , And an integer close to our decimal ;
D、 Round to the nearest whole
This should be the most understandable .
Take a chestnut :
-3.79 integer , Namely -4;
-3.1 integer , Namely -3;
3.9 integer , Namely 4;
Write a code and feel the following overall :
#include<math.h>
int main()
{
float a, b, c, d, e;
a = 1.0f;
b = 2.1f;
c = -1.3f;
d = -0.2f;
e = 3.76f;
printf("f_val\ttrunc\tfloor\tceil\tround\n");
printf("%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n", a, trunc(a), floor(a), ceil(a), round(a));
printf("%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n", b, trunc(b), floor(b), ceil(b), round(b));
printf("%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n", c, trunc(c), floor(c), ceil(c), round(c));
printf("%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n", d, trunc(d), floor(d), ceil(d), round(d));
printf("%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n", e, trunc(e), floor(e), ceil(e), round(e));
return 0;
}
Run a screenshot :
The header file :#include<math.h>
trunc() The function is directed to 0 integer ;
floor() The function is rounded to negative infinity ;
ceil() The function is rounded to positive infinity ;
round() The function is rounding ;
C The language is directed 0 integer ;
For example, in C In language
-3.14 Rounding is -3;
stay python Is rounded to negative infinity ;
stay python in -3.14 Rounding is -4;
2、 Talk about taking mold
Mold concept : If a and d It's a natural number ,d Not 0, It can be proved that there are two unique integers q and r, Satisfy a=q*d+r, And 0<=r<d, among q It's called business ,r It's called the remainder ;
Then let's take a look at the following code ;
among 10=(q)*3+(r)
According to the direction 0 Rounding principle ,q=3, so r=1;
What if it's negative ?
According to the above rules :
-10=(q)3+(r);
towards 0 Rounding principle :q=-3, so r=-1;
This seems to conflict with the above definition ,r<0 了 , To solve this problem , We revised the definition : If a and d It's a natural number ,d Not 0, It can be proved that there are two unique integers q and r, Satisfy a=qd+r, And 0<=|r|<|d|, among q It's called business ,r It's called the remainder ;
With this definition ,C In language r It can be explained by being negative ;
The above does not mean , stay python Is the rounding method different in ? that -10/3 And -10%3 Is the result the same ?
Through verification, it is found that the results are different :
analysis :-10/3 yes -3.33333…, Round to negative infinity ,-10/3 It should be -4;
Empathy :-10=(q)*3+(r);q=-4, so r=2;
3、 What determines this phenomenon ?
Through the analysis above , We come to the conclusion that
stay C In language ,-10%3=-1;
stay python in ,-10%3=2;
So what is the reason ? We know , The remainder is determined by quotient , What determines the quotient ? It's because of the rounding method ; stay C Language and python The difference in rounding method between the two , It's caused “ modulus ” The difference of ; That's why % Operator , In different languages , The meaning is different ;
4、 Is the mold the same as the remainder ?
Most of the time they mean the same thing , But strictly speaking, this is not the case :
modulus : The way to take quotient is to round it like negative infinity ;
Remainder : The way to get quotient is to follow the example 0 The way of rounding ;
about C language % It means taking the remainder ;
about python Come on % Representative mould ;
So how to judge a language % Does it represent remainder or module ?
You can use the following code to test :
C Language ( or C++) Under the language ,% Is a remainder operation ;
int main()
{
int a = -10;
int b = 3;
if (a / b == -3)
{
printf("%% Do the remainder operation \n");
printf("%d\n", a / b);
}
else
{
printf("%% Modulo operation done \n");
printf("%d\n",a/b);
}
return 0;
}

边栏推荐
- I have seven schemes to realize web real-time message push, seven!
- STM32 development note 120: solve the problem that%f in printf cannot be output
- HMS Core Discovery第16期直播预告|与虎墩一起,玩转AI新“声”态
- Three must know and know problems of redis
- DOM在Ahooks中的处理过程
- Luogu p2391 snow covered problem solution
- Nexttick principle analysis
- RHCE first day
- STL notes (VIII): container - List
- STM32 development note 117: generate IIR low-pass filter coefficients using MATLAB
猜你喜欢
随机推荐
Summary and Prospect of aut, the transport layer protocol of sound network -- dev for dev column
rhcsa暑假第二天
Matter's Unified Smart Home connection standard enables local automatic interaction between smart devices
[small program practice] first day
[literature notes] pointmlp
初步了解Panda3d粒子系统
Gradle test and idea test
I will write some Q & A blogs recently, mainly focusing on the points that are easy to have doubts.
Render Optimization: repaint and reflow
Interviewer: explain the core principle of ThreadLocal
Docker builds MySQL master-slave replication
Learning records [email protected] R & D effectiveness measurement indicators
如何判断是否遭到DDOS攻击
Compile ue5.0
Permanent magnet synchronous motor 36 question (1) -- what is the difference between salient pole motor and salient pole motor?
STM32 development note 120: solve the problem that%f in printf cannot be output
学习记录[email protected]研发效能度量指标
Baklib: share some methods about building enterprise knowledge management (km)
Get the parameters of the browser address bar
Special analysis of data security construction in banking industry









