精华内容
下载资源
问答
  • 取余的公式: 余数=除数-被除数*商 python的的余数是按照整除(向下取整)得到的商来计算的。 取余问题主要分为 : 正数与正数,负数与负数,正数与负数 ,0 正数与正数 #大数/小数:因为得出的商和整除得出的一致...
  • 主要介绍了C#编程实现取整和取余的方法,结合实例形式分析了C#中Math.Celling与Math.Floor函数的相关使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • 主要介绍了Java别说取余(%)运算简单你真的会吗,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • FPGA\Verilog实现开方、平方、取余等数学算法,已经在硬件中实际验证过,计算没有问题,验证硬件是黑金的AX530
  • python实现取余操作的方法: 可以利用求模运算符(%)来实现。求模运算符可以将两个数相除得到其余数。我们还可以使用divmod()函数来实现取余操作,具体方法如:【divmod(10,3)】。 在python中要实现取余操作可以...
  • ASP(VBScript) 中取余用 mod,比如 m = 5 mod 2,结果为 1。 大数注意 m = 4444444444 / 2 n = 4444444444 \ 2 第一句是正确的,第二句运行时会报溢出错误,因为:在整除、取余操作前,数值表达式四舍五入为 Byte、...
  • c++和C#中,运算符‘%’为取余运算符,而并非取模预算符,在一些应用场景中,如果不加以区分,会产生严重的bug。
  • 主要介绍了PHP中余数、取余的妙用,这个是在WEB开发中一个经常使用的小技巧,不管是在表格、ul、li或者是换行等HTML处理中,需要隔几行换行,隔几行加入ul或li的结束标记等时候,特别的有用,需要的朋友可以参考下
  • /为班级30个人的姓名设计一个哈希表,假设姓名用汉语拼音表示。要求用除留余数法 ...2、创建哈希表,将ASCII码取余得KEY值,若未发生冲突存入哈希表 3、发生冲突调用冲突函数。进行线性探测。最后存入哈希表。
  • 主要介绍了基于Python编写一个计算器程序,实现简单的加减乘除和取余二元运算,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 结合lambda表达式、函数调用运算符、标准库函数对象、C++11标准新增的标准库function类型,编写一个简单的计算器,可实现简单的加、减、乘、除、取余二元运算。代码如下: #include "pch.h" #include #include #...
  • 主要介绍了Java中的相除(/)和取余(%)的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 取余

    2019-12-04 20:17:20
    例28 需求:100以内被3整除的数之和 #!/bin/bash sum=0 for i in `seq 1 100` do n=$(($i%3)) if [ $n == 0 ] then sum=$[$sum+$i] fi done echo $sum 知识点:%取余 ...

    例28

    需求:100以内被3整除的数之和

    #!/bin/bash
    sum=0
    for i in `seq 1 100`
    do
            n=$(($i%3))
            if [ $n == 0 ]
            then
                    sum=$[$sum+$i]
            fi
    done
    echo $sum
    

    知识点:%取余

    展开全文
  • 快速求幂和取余 C++

    2017-12-15 16:36:27
    C++ 快速计算求幂和取余,代码已测试,可直接使用。。。
  • Swift教程:基本操作符 赋值和算术运算及取余视频教程
  • 其中,关于负数取余这一个小问题,书中是用整除(//)来解释的,感觉不是很清楚。然后看了个教程是这样的,仔细一看也是有问题的。 1.圆整 就是把一个小数或者说浮点数按某种规律近似为一个它左边或右边最近的一个...

    1.圆整

    就是把一个小数或者说浮点数按某种规律近似为一个它左边或右边最近的一个整数。比如:

    1. 向负无穷圆整
       1.8->1
      1.2->1
     -0.4->-1
     -0.7->-1
    
    1. 向零圆整
    1.6->1
    1.2->1
    -0.4->0
    -0.7->0
    
    1. 四舍五入圆整
    1.6->2
    1.3->1
    -0.2->0
    -0.7->-1
    

    在python有一个函数为round(),有点小特别,一般情况下为:

    >>> round(1.2) 
    1.0
    >>> round(1.6)
    2.0
    >>> round(-0.2)
    -0.0
    >>> round(-0.7)
    -1.0
    

    好像还在在意料之中。

    特例1:

    #python 3
    >>>round(3.5)
    >>>4
    >>>round(2.5)
    >>>2
    
    #python 2
    
    >>> round(3.5)
    4.0
    >>> round(2.5)
    3.0
    >>> 
    

    解析:

    python2中如果浮点数距离两端一样远,则保留到离0远的一边。所以round(0.5)会近似到1,而round(-0.5)会近似到-1。

    python3.5中如果距离两边一样远,会保留到偶数的一边。比如round(0.5)和round(-0.5)都会保留到0,而round(1.5)会保留到2。

    特例2:

    #python 2 or python 3
    >>> round(2.675,2)
    2.67
    

    后面的2表示要保留的小数位数,结果为什么不是2.68呢?

    解析:

    这跟浮点数的精度有关。我们知道在机器中浮点数不一定能精确表达,因为换算成一串1和0后可能是无限位数的,机器已经做出了截断处理。那么在机器中保存的2.675这个数字就比实际数字要小那么一点点。这一点点就导致了它离2.67要更近一点点,所以保留两位小数时就近似到了2.67。关于浮点数,并不是想象中那样简单,后面我会补充一篇相关文章。

    到这里,对于python而言,我要说:

    除非对精确度没什么要求,否则尽量避开用round()函数。或者选择其他方法。
    
    1)使用math模块中的一些函数,比如math.ceiling(天花板除法)。
    2)python自带整除,python2中是/3中是//,还有div函数。
    3)字符串格式化可以做截断使用,例如 "%.2f" % value(保留两位小数并变成字符串……如果还想用浮点数请披上float()的外衣)。
    4)对浮点数精度要求如果很高的话,请用decimal模块。
    

    2.取余与取模

       通常情况下,我们对取余和取模混为一谈,但是这两个是不一样的。在c、 c++ 、java、 python里面都是用%表示取模或者取余的,但是我们分别用这四门语言去计算-1%3这个式子发现结果并不一样,原因是在c、 c++、 java里面%表示取余,而在python里面%表示取模。而我开头提到的那本书直接将其混为一谈,越看越气。

       进行计算的两个数符号一样时,取余和取模的结果是一样的,因为符号一样时a/b总是非负数,那么a%b的结果自然也是一样的,这里不再讨论。

       在进行计算的两个数符号不一样时,取余和取模的结果是不一样的,究其原因是下面公式中在计算c的时候趋向不同。

       下面的式子中:c表示a/b的商的整数部分(虽然//表示取整,但用它来表示取余或者取模的商的整数部分是不合理的,此处仅仅作为一个记号使用),则r则为取余或者取模的结果。取余或者取余的不同指出就在与:c的取值不同,取余计算中c是向0取整,取模计算中c是向负无穷取整

    c=a//b;
    a=c*b+r;
    

    3.实例解析

    先来几道题目给大家做做吧:

    #分别计算下面4式取余和取模的结果
    >>>  10 % 3
    >>>  -10 % -3
    >>>  -10 % 3
    >>>> 10 % -3
    

    先睡觉了,明天补上下文

    展开全文
  • 位运算和取余

    2021-10-22 09:53:44
    二进制的魔法取余和与1. 与(&)的真面目2. << 左移3. >> 右移4. % 取余 取余和与 1. 与(&)的真面目 A B A&B 0 0 0 0 1 0 1 0 0 1 1 1 可以看出,在二进制的位运算中: ...

    取余

    1. 与(&)的真面目

    ABA&B
    000
    010
    100
    111

    可以看出,在二进制的位运算中:

    1. 不管是 0 还是 1& 1 的结果都是 本身
    2. 不管是 0 还是 1& 0 的结果都是 0

    1   &   x = x x ∈ ( 0 , 1 ) ⇒ p e r s i s t 0   &   x = 0 x ∈ ( 0 , 1 ) ⇒ r e s e t \begin{aligned} &1\ \&\ x=x\quad x\in(0,1)\Rightarrow persist\\ &0\ \&\ x=0\quad x\in(0,1)\Rightarrow reset \end{aligned} 1 & x=xx(0,1)persist0 & x=0x(0,1)reset

    2. << 左移

    假设,有 4 4 4 位二进制数 x 4 x 3 x 2 x 1 x_4x_3x_2x_1 x4x3x2x1 ,乘以 2 3 2^3 23

    x 4 x 3 x 2 x 1 × 2 3 =   ( x 4 ⋅ 2 3 + x 3 ⋅ 2 2 + x 2 ⋅ 2 1 + x 1 ⋅ 2 0 ) × 2 3 =   x 4 ⋅ 2 6 + x 3 ⋅ 2 5 + x 2 ⋅ 2 4 + x 1 ⋅ 2 3 =   x 4 x 3 x 2 x 1 000 \begin{aligned} &x_4x_3x_2x_1\times2^3\\ =&\ (x_4\cdot2^3 + x_3\cdot2^2 + x_2\cdot2^1 + x_1\cdot2^0)\times2^3\\ =&\ x_4\cdot2^6 + x_3\cdot2^5 + x_2\cdot2^4 + x_1\cdot2^3\\ =&\ x_4x_3x_2x_1000 \end{aligned} ===x4x3x2x1×23 (x423+x322+x221+x120)×23 x426+x325+x224+x123 x4x3x2x1000
    可以看出,任何一个二进制数,乘以 2 N 2^N 2N ,就是将原来的数字,左移 N N N 位,后面补 0 0 0

    3. >> 右移

    假设,有 4 4 4 位二进制数 x 4 x 3 x 2 x 1 x_4x_3x_2x_1 x4x3x2x1 ,除以 2 2 2^2 22

    x 4 x 3 x 2 x 1 ÷ 2 2 =   ( x 4 ⋅ 2 3 + x 3 ⋅ 2 2 + x 2 ⋅ 2 1 + x 1 ⋅ 2 0 ) ÷ 2 2 =   x 4 ⋅ 2 1 + x 3 ⋅ 2 0 + x 2 ⋅ 2 − 1 + x 1 ⋅ 2 − 2 =   x 4 x 3   ⋯   x 2 x 1 \begin{aligned} &x_4x_3x_2x_1\div2^2\\ =&\ (x_4\cdot2^3 + x_3\cdot2^2 + x_2\cdot2^1 + x_1\cdot2^0)\div2^2\\ =&\ x_4\cdot2^1+x_3\cdot2^0+x_2\cdot2^{-1}+x_1\cdot2^{-2}\\ =&\ x_4x_3\ \cdots\ x_2x_1 \end{aligned} ===x4x3x2x1÷22 (x423+x322+x221+x120)÷22 x421+x320+x221+x122 x4x3  x2x1

    可以看出,任何一个二进制数,除以 2 N 2^N 2N ,就是将原来的数字,右移 N N N 位。移出去的,是 余数

    x 4 x 3 x 2 x 1   %   2 2 = x 2 x 1 x_4x_3x_2x_1\ \%\ 2^2 = x_2x_1 x4x3x2x1 % 22=x2x1

    4. % 取余

    既然,当除数是 2 N 2^N 2N ,余数是挪出去的那 N N N 位,对于取余运算来说,提取出最后的 N N N 位就可以了。怎么做呢?清零 & 保留

    假设,有 4 4 4 位二进制数 x 4 x 3 x 2 x 1 x_4x_3x_2x_1 x4x3x2x1 ,取余 2 2 2^2 22

    x 4 x 3 x 2 x 1   %   2 2 =   x 4 x 3 x 2 x 1   &   ( 2 2 − 1 ) =   x 4 x 3 x 2 x 1   &   0011 =   x 2 x 1 \begin{aligned} &x_4x_3x_2x_1\ \%\ 2^2\\ =&\ x_4x_3x_2x_1\ \&\ (2^2-1)\\ =&\ x_4x_3x_2x_1\ \&\ 0011\\ =&\ x_2x_1 \end{aligned} ===x4x3x2x1 % 22 x4x3x2x1 & (221) x4x3x2x1 & 0011 x2x1

    可以看出,任何一个二进制数,取余 2 N 2^N 2N ,就可以 & ( 2 N − 1 ) (2^N-1) (2N1) 。得到需要右移的 N N N 位。

    展开全文
  • C++中取余运算的优化

    千次阅读 2019-09-16 10:39:39
    )没有被编译成汇编代码,可能的原因是,那些被优化掉的代码对程序的运行结果没有任何影响,因此被编译器跳过了,这依然不是我们想要的,为了能够在汇编层面看到C++对取余运算做的优化,我们还需要将程序写的更复杂...

    0、前言

    gcc/g++编译优化选项:-O
    这个选项控制所有的优化等级。使用优化选项会使编译过程耗费更多的时间,并且占用更多的内存,尤其是在提高优化等级的时候。
    -O设置一共有五种:-O0、-O1、-O2、-O3和-Os。你只能在/etc/make.conf里面设置其中的一种。
    除了-O0以外,每一个-O设置都会多启用几个选项,请查阅gcc手册的优化选项章节,以便了解每个-O等级启用了哪些选项及它们有何作用。
    让我们来逐一考察各个优化等级:

    • -O0:这个等级(字母“O”后面跟个零)关闭所有优化选项,也是CFLAGS或CXXFLAGS中没有设置-O等级时的默认等级。这样就不会优化代码,这通常不是我们想要的。
    • -O1:这是最基本的优化等级。编译器会在不花费太多编译时间的同时试图生成更快更小的代码。这些优化是非常基础的,但一般这些任务肯定能顺利完成。
    • -O2:-O1的进阶。这是推荐的优化等级,除非你有特殊的需求。-O2会比-O1启用多一些标记。设置了-O2后,编译器会试图提高代码性能而不会增大体积和大量占用的编译时间。
    • -O3:这是最高最危险的优化等级。用这个选项会延长编译代码的时间,并且在使用gcc4.x的系统里不应全局启用。自从3.x版本以来gcc的行为已经有了极大地改变。在3.x,-O3生成的代码也只是比-O2快一点点而已,而gcc4.x中还未必更快。用-O3来编译所有的软件包将产生更大体积更耗内存的二进制文件,大大增加编译失败的机会或不可预知的程序行为(包括错误)。这样做将得不偿失,记住过犹不及。在gcc 4.x.中使用-O3是不推荐的。
    • -Os:这个等级用来优化代码尺寸。其中启用了-O2中不会增加磁盘空间占用的代码生成选项。这对于磁盘空间极其紧张或者CPU缓存较小的机器非常有用。但也可能产生些许问题,因此软件树中的大部分ebuild都过滤掉这个等级的优化。使用-Os是不推荐的。

    1、实验一

    假设现在有如下demo示例:

    
    1 int main(void) {
    2     int a = 100 % 128;
    3     return 0;
    4 }
    

    不指定优化选项时的汇编代码(默认为-O0)

     1
     2 test.o: file format Mach-O 64-bit x86-64
     3
     4 Disassembly of section __TEXT,__text:
     5 _main:
     6 ; int main(void) {
     7        0:   55  pushq   %rbp
     8        1:   48 89 e5    movq    %rsp, %rbp
     9        4:   31 c0   xorl    %eax, %eax
    10        6:   c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
    11 ; int a = 100 % 128;
    12        d:   c7 45 f8 64 00 00 00    movl    $100, -8(%rbp)
    13 ; return 0;
    14       14:   5d  popq    %rbp
    15       15:   c3  retq

    结论:虽然没有指定优化选项,但g++还是将100 % 128的结果(100)在编译的时候算出来了,在第12行的地方,通过movl  $100, -8(%rbp)指令,将100赋值给了变量a,这不是我们想要的,为了能够在汇编层面看到C++计算取余的方法,我们还需要将程序写的复杂一些,以便能够绕过g++的编译优化。

    2、实验二

    假设现在有如下demo示例:

    1 int main(void) {
    2     int a = 100;
    3     int b = a % 128;
    4     return 0;
    5 }

    不指定优化选项时的汇编代码(默认为-O0)

     1
     2 test.o: file format Mach-O 64-bit x86-64
     3
     4 Disassembly of section __TEXT,__text:
     5 _main:
     6 ; int main(void) {
     7        0:   55  pushq   %rbp
     8        1:   48 89 e5    movq    %rsp, %rbp
     9        4:   31 c0   xorl    %eax, %eax
    10        6:   c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
    11 ; int a = 100;
    12        d:   c7 45 f8 64 00 00 00    movl    $100, -8(%rbp)
    13 ; int b = a % 128;
    14       14:   8b 4d f8    movl    -8(%rbp), %ecx
    15       17:   89 45 f0    movl    %eax, -16(%rbp)
    16       1a:   89 c8   movl    %ecx, %eax
    17       1c:   99  cltd
    18       1d:   b9 80 00 00 00  movl    $128, %ecx
    19       22:   f7 f9   idivl   %ecx
    20       24:   89 55 f4    movl    %edx, -12(%rbp)
    21 ; return 0;
    22       27:   8b 4d f0    movl    -16(%rbp), %ecx
    23       2a:   89 c8   movl    %ecx, %eax
    24       2c:   5d  popq    %rbp
    25       2d:   c3  retq

    结论:在第19行的地方,通过idivl %ecx指令,用eax寄存器(存的是100)里的值除以ecx寄存器(存的是128)里的值,并将余数存放在edx寄存器,商存放在eax寄存器。在第20行的地方,通过movl %edx, -12(%rbp)指令,将edx寄存器(存的是余数)放入变量b中。因此,从第19行的代码可以看出,当对128(2^7)进行取余时,编译器并未通过位运算的方式对取余操作进行优化。

    指定优化选项为-O1时的汇编代码

     1
     2 test.o: file format Mach-O 64-bit x86-64
     3
     4 Disassembly of section __TEXT,__text:
     5 _main:
     6 ; int main(void) {
     7        0:   55  pushq   %rbp
     8        1:   48 89 e5    movq    %rsp, %rbp
     9 ; return 0;
    10        4:   31 c0   xorl    %eax, %eax
    11        6:   5d  popq    %rbp
    12        7:   c3  retq

    结论:开启-O1编译优化选项后,main函数中的两条语句(int a = 100; int b = a % 128;)没有被编译成汇编代码,可能的原因是,那些被优化掉的代码对程序的运行结果没有任何影响,因此被编译器跳过了,这依然不是我们想要的,为了能够在汇编层面看到C++对取余运算做的优化,我们还需要将程序写的更复杂一些,以便能够绕过g++最基本的优化,同时也能看到对取余运算的优化。

    3、实验三

    假设现在有如下demo示例:

    1 int b = 0;
    2 int foo(int x) {
    3     return x * x;
    4 }
    5 int main(void) {
    6     int a = foo(10);
    7     b = a % 128;
    8     return 0;
    9 }

    指定优化选项为-O1时的汇编代码

    1
     2 test.o: file format Mach-O 64-bit x86-64
     3
     4 Disassembly of section __TEXT,__text:
     5 __Z3fooi:
     6 ; int foo(int x) {
     7        0:   55  pushq   %rbp
     8        1:   48 89 e5    movq    %rsp, %rbp
     9 ; return x * x;
    10        4:   0f af ff    imull   %edi, %edi
    11        7:   89 f8   movl    %edi, %eax
    12        9:   5d  popq    %rbp
    13        a:   c3  retq
    14        b:   0f 1f 44 00 00  nopl    (%rax,%rax)
    15
    16 _main:
    17 ; int main(void) {
    18       10:   55  pushq   %rbp
    19       11:   48 89 e5    movq    %rsp, %rbp
    20 ; int a = foo(10);
    21       14:   bf 0a 00 00 00  movl    $10, %edi
    22       19:   e8 00 00 00 00  callq   0 <_main+0xe>
    23 ; b = a % 128;
    24       1e:   89 c1   movl    %eax, %ecx
    25       20:   c1 f9 1f    sarl    $31, %ecx
    26       23:   c1 e9 19    shrl    $25, %ecx
    27       26:   01 c1   addl    %eax, %ecx
    28       28:   83 e1 80    andl    $-128, %ecx
    29       2b:   29 c8   subl    %ecx, %eax
    30       2d:   89 05 00 00 00 00   movl    %eax, (%rip)
    31 ; return 0;
    32       33:   31 c0   xorl    %eax, %eax
    33       35:   5d  popq    %rbp
    34       36:   c3  retq

    结论:开启-O1编译优化选项后,可以看到当128作为除数进行取余运算时,g++通过位运算做了优化,涉及到的汇编代码及其作用如下表所示

    行号指令作用备注
    25
    sarl    $31, %ecx
    将ecx寄存器中的数(被除数)算数右移31位,最高位补符号位,得到结果是,当被除数为正数时,ecx中存的是32个0,当被除数为负数时,ecx中存的是32个1。 
    26
    shrl    $25, %ecx
    将ecx寄存器中的数逻辑右移25位,最高位补0,结合第25行的逻辑,得到的结果是,当被除数为正数时,ecx中存的是32个0,当被除数为负数时,ecx中存的是25个0和7个1,即127。 
    27
    addl    %eax, %ecx
    将eax寄存器中的数(被除数)加上ecx寄存器中的数(0或127)放入ecx寄存器中,这样做的原因是,C++的取余运算在计算商值时,向0方向舍弃小数位,也就是说当被除数为负数时,商乘以除数的值要大于等于被除数。即,为了使第28行中的ecx & (-128)大于等于被除数,需要在第27中将ecx加上127。 
    28
    andl    $-128, %ecx
    将ecx寄存器中的数按位与-128,得到(ecx/128)*128,即商与除数的乘积,其中 (ecx/128) 向0方向舍弃小数位。 
    29
    subl    %ecx, %eax
    将eax寄存器中的数(被除数)减去ecx寄存器中的数放入eax寄存器中,即被除数减去商与除数的乘积,得到余数。 

    为了进一步说明上述汇编代码中的立即数25(32-7)、-128与demo中的128(2^7)有直接的关系,下面将demo中的128换成1024(2^10),然后再对比汇编代码的不同。

    4、实验四

    假设现在有如下demo示例:

    1 int b = 0;
    2 int foo(int x) {
    3     return x * x;
    4 }
    5 int main(void) {
    6     int a = foo(10);
    7     b = a % 1024;
    8     return 0;
    9 }

    指定优化选项为-O1时的汇编代码

    1
     2 test.o: file format Mach-O 64-bit x86-64
     3
     4 Disassembly of section __TEXT,__text:
     5 __Z3fooi:
     6 ; int foo(int x) {
     7        0:   55  pushq   %rbp
     8        1:   48 89 e5    movq    %rsp, %rbp
     9 ; return x * x;
    10        4:   0f af ff    imull   %edi, %edi
    11        7:   89 f8   movl    %edi, %eax
    12        9:   5d  popq    %rbp
    13        a:   c3  retq
    14        b:   0f 1f 44 00 00  nopl    (%rax,%rax)
    15
    16 _main:
    17 ; int main(void) {
    18       10:   55  pushq   %rbp
    19       11:   48 89 e5    movq    %rsp, %rbp
    20 ; int a = foo(10);
    21       14:   bf 0a 00 00 00  movl    $10, %edi
    22       19:   e8 00 00 00 00  callq   0 <_main+0xe>
    23 ; b = a % 1024;
    24       1e:   89 c1   movl    %eax, %ecx
    25       20:   c1 f9 1f    sarl    $31, %ecx
    26       23:   c1 e9 16    shrl    $22, %ecx
    27       26:   01 c1   addl    %eax, %ecx
    28       28:   81 e1 00 fc ff ff   andl    $4294966272, %ecx
    29       2e:   29 c8   subl    %ecx, %eax
    30       30:   89 05 00 00 00 00   movl    %eax, (%rip)
    31 ; return 0;
    32       36:   31 c0   xorl    %eax, %eax
    33       38:   5d  popq    %rbp
    34       39:   c3  retq
    结论:由上述汇编代码可知,当除数换成1024之

    结论:由上述汇编代码可知,当除数换成1024之后,实验三中第26行的立即数25变成了22(32-10),第28行的立即数-128变成了4294966272(即-1024的补码),其他内容不变。由此可以看出,在C++程序进行编译时,若源码中出现了对2的幂进行取余的操作,且开启了-O1优化选项,那么在随后生成的汇编代码中,是通过位运算实现取余操作的。不过,值得注意的是,在我们的源码中进行取余操作时,我们是通过立即数的形式指定了2的幂,那如果我们通过变量的形式指定2的幂(这可能是更常见的情况),结果会如何呢?

    5、实验五

    假设现在有如下demo示例:

     1 int b = 0;
     2 int foo(int x) {
     3     return x * x;
     4 }
     5 int goo(int x) {
     6     return 1 << x;
     7 }
     8 int main(void) {
     9     int a = foo(10);
    10     int c = goo(10);
    11     b = a % c;
    12     return 0;
    13 }

    指定优化选项为-O1时的汇编代码

     1
     2 test.o: file format Mach-O 64-bit x86-64
     3
     4 Disassembly of section __TEXT,__text:
     5 __Z3fooi:
     6 ; int foo(int x) {
     7        0:   55  pushq   %rbp
     8        1:   48 89 e5    movq    %rsp, %rbp
     9        4:   89 7d fc    movl    %edi, -4(%rbp)
    10 ; return x * x;
    11        7:   8b 7d fc    movl    -4(%rbp), %edi
    12        a:   0f af 7d fc     imull   -4(%rbp), %edi
    13        e:   89 f8   movl    %edi, %eax
    14       10:   5d  popq    %rbp
    15       11:   c3  retq
    16       12:   66 2e 0f 1f 84 00 00 00 00 00   nopw    %cs:(%rax,%rax)
    17       1c:   0f 1f 40 00     nopl    (%rax)
    18
    19 __Z3gooi:
    20 ; int goo(int x) {
    21       20:   55  pushq   %rbp
    22       21:   48 89 e5    movq    %rsp, %rbp
    23       24:   89 7d fc    movl    %edi, -4(%rbp)
    24 ; return 1 << x;
    25       27:   8b 4d fc    movl    -4(%rbp), %ecx
    26       2a:   bf 01 00 00 00  movl    $1, %edi
    27       2f:   d3 e7   shll    %cl, %edi
    28       31:   89 f8   movl    %edi, %eax
    29       33:   5d  popq    %rbp
    30       34:   c3  retq
    31       35:   66 2e 0f 1f 84 00 00 00 00 00   nopw    %cs:(%rax,%rax)
    32       3f:   90  nop
    33
    34 _main:
    35 ; int main(void) {
    36       40:   55  pushq   %rbp
    37       41:   48 89 e5    movq    %rsp, %rbp
    38       44:   48 83 ec 10     subq    $16, %rsp
    39       48:   c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
    40 ; int a = foo(10);
    41       4f:   bf 0a 00 00 00  movl    $10, %edi
    42       54:   e8 00 00 00 00  callq   0 <_main+0x19>
    43       59:   89 45 f8    movl    %eax, -8(%rbp)
    44 ; int c = goo(10);
    45       5c:   bf 0a 00 00 00  movl    $10, %edi
    46       61:   e8 00 00 00 00  callq   0 <_main+0x26>
    47       66:   31 ff   xorl    %edi, %edi
    48       68:   89 45 f4    movl    %eax, -12(%rbp)
    49 ; b = a % c;
    50       6b:   8b 45 f8    movl    -8(%rbp), %eax
    51       6e:   99  cltd
    52       6f:   f7 7d f4    idivl   -12(%rbp)
    53       72:   89 15 00 00 00 00   movl    %edx, (%rip)
    54 ; return 0;
    55       78:   89 f8   movl    %edi, %eax
    56       7a:   48 83 c4 10     addq    $16, %rsp
    57       7e:   5d  popq    %rbp
    58       7f:   c3  retq

    结论:从第52行idivl -12(%rbp)指令可以看出,当我们通过变量的形式指定2的幂时,开启-O1优化后,在得到的汇编代码中并没有通过位运算来优化取余操作。既然开启-O1优化选项后并没有得到我们想要的优化效果,那么可以尝试一下-O2优化选项。

    6、实验六

    假设现在有如下demo示例:

     1 int b = 0;
     2 int foo(int x) {
     3     return x * x;
     4 }
     5 int goo(int x) {
     6     return 1 << x;
     7 }
     8 int main(void) {
     9     int a = foo(10);
    10     int c = goo(10);
    11     b = a % c;
    12     return 0;
    13 }

    指定优化选项为-O2时的汇编代码

     1
     2 test.o: file format Mach-O 64-bit x86-64
     3
     4 Disassembly of section __TEXT,__text:
     5 __Z3fooi:
     6 ; int foo(int x) {
     7        0:   55  pushq   %rbp
     8        1:   48 89 e5    movq    %rsp, %rbp
     9 ; return x * x;
    10        4:   0f af ff    imull   %edi, %edi
    11        7:   89 f8   movl    %edi, %eax
    12        9:   5d  popq    %rbp
    13        a:   c3  retq
    14        b:   0f 1f 44 00 00  nopl    (%rax,%rax)
    15
    16 __Z3gooi:
    17 ; int goo(int x) {
    18       10:   55  pushq   %rbp
    19       11:   48 89 e5    movq    %rsp, %rbp
    20       14:   b8 01 00 00 00  movl    $1, %eax
    21 ; return 1 << x;
    22       19:   89 f9   movl    %edi, %ecx
    23       1b:   d3 e0   shll    %cl, %eax
    24       1d:   5d  popq    %rbp
    25       1e:   c3  retq
    26       1f:   90  nop
    27
    28 _main:
    29 ; int main(void) {
    30       20:   55  pushq   %rbp
    31       21:   48 89 e5    movq    %rsp, %rbp
    32 ; b = a % c;
    33       24:   c7 05 fc ff ff ff 64 00 00 00   movl    $100, -4(%rip)
    34 ; return 0;
    35       2e:   31 c0   xorl    %eax, %eax
    36       30:   5d  popq    %rbp
    37       31:   c3  retq

    结论:从第33行的 movl $100, -4(%rip) 指令可以看出,开启-O2优化选项后,g++直接在编译阶段将 (x * x) % (1 << x)的结果(100)计算出来了,其中x=10。可能,这才是g++强大的优化能力。

    7、参考文献

    https://blog.csdn.net/attagain/article/details/18655485

    https://blog.csdn.net/coder_panyy/article/details/73743722

    展开全文
  • 今天看到个RSA的资料,感觉挺有意思于是研究了一下。程序是按照我的理解初步实现了一下数字的加解密。里面涉及到的知识有RSA的原理,在设定范围内产生随机的质数,如何求最大公约数, 最小公倍数,其实这些都还可以...
  • Matlab取余

    千次阅读 2019-12-13 15:38:43
    matlab使用%作为注释标志,但是可以使用mod()用来代替。 >> a=[2,3,4] a = 2 3 4 >> mod(a,2) ans = 0 1 0 >> a=[1,2,3;4,5,6] a = 1 2 3 4 5 6 >&...
  • 大数取余方法

    2021-03-09 17:08:27
    在 int32 的存储条件下,大数计算乘法,可能会超出数值范围,导致返回值错误 1. 循环求余法 把指数操作转换成一次次的乘法,每次相乘就取以此余数,使得数值不超过范围 ...2. 快速幂取余 计算a^n % b,其中a,b和n都
  • 这篇文章主要介绍 C 语言和 Python 在取余操作上的异同。阅读本文预计需要 6 分钟。 C 语言和 Python 在取余操作上的异同前言C 语言和 Python 中的取余算法向 0 取整 VS 向负无穷取整C 语言中的除法和取余测试...
  • 取余运算

    千次阅读 2019-08-16 01:36:12
    关于取余运算 关于取余运算 两个数 n d 进行取余,记为: n % d (d !== 0). 对于结果 r 的正负性,可以规定为,与 n 的符号一致. 见下面的mod函数. console.log('-12%5:',-12%5); console.log('12%-5:',12%-5); ...
  • c++取余运算

    2021-08-04 00:46:57
    C++中取余运算负数和正数的数字部分相同,成相反数。例: −2%10=−2=−(2%10) -2\%10=-2=-(2\%10) −2%10=−2=−(2%10) 该定义不满足 x=xmod  q+q∗⌊xq⌋ x=x \mod q+q*\lfloor \frac{x}{q}\rfloor x=xmodq+q∗...
  • Java中取模与取余

    2021-07-13 20:48:48
    通常取模运算也叫取余运算,它们返回的结果都是余数。rem(取余)和mod(取模)唯一的区别在于:当X和Y的正负号一样的时候,两个函数结果是等同的;当X和Y的符号不同时,rem(取余)函数的结果的符号和X的符号一样,而mod...
  • C语言入门——取余运算

    千次阅读 热门讨论 2021-09-09 13:48:42
    C语言入门——简单的取余运算 学习C语言时,我们可能会遇到%,在平常的数学或其他学科学习时,我们运用%可能更多的是作为百分号来使用,因此对它在C语言中的功能可以说是熟悉又陌生。但是我们对+ - * /比较熟悉,...
  • C语言 负数取余

    2021-08-30 20:10:21
    如果 % 左边的操作数是正数,则取余的结果为正数或零;如果 % 左边的操作数是负数,则取余的结果为负数或零。例如: 13% 2 // 余 1 13% -2 // 余 1 -13% 2 // 余 -1 -13% -2 // 余 -1 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 115,736
精华内容 46,294
关键字:

取余