前言

Java 中常见的取模和取余(求余)计算,在我们日常的很多业务领域都有用到。比如当我们做数据加密时,密码学中不同的加密方案底层会采用不同的模运算来决定其复杂度;做游戏的同学游戏引擎中的取余求最高点;银行金融系统计算中间件开发;随机函数、一致性Hash等等。

问了办公室同样做开发几年的同事,居然对两者区别毫不知晓。转问办公室另一即将科班毕业研究生,对概念也是模糊不清。于是决定总结一下,写下这篇文章。

概念

通常取模运算也叫取余运算,它们返回结果都是余数 .remmod 唯一的区别在于:

当 x 和 y 的正负号一样的时候,两个函数结果是等同的;当 x 和 y 的符号不同时,rem 函数结果的符号和 x 的一样,而 mod 和 y 一样。

这是由于这两个函数的生成机制不同,rem 函数采用 fix 函数,而 mod 函数采用了 floor 函数(这两个函数是用来取整的,fix 函数向 0 方向舍入,floor 函数向无穷小方向舍入)。 rem(x,y)命令返回的是 x-n.y,如果 y 不等于 0,其中的 n = fix(x./y),而 mod(x,y) 返回的是 x-n.y,当 y 不等于 0 时,n=floor(x./y)

卧槽~ 这是什么鬼 是不是觉得看不懂,下面涛哥用简单的示例来进行介绍,给你整得明明白白的。

Java 示例

我们就创建一个测试类,来进行示例说明

  • 当 x 和 y 的正负号一样的时候,两个函数结果是等同的

    package org.taoguoguo.hyper;
    
    /**
    * @author taoguoguo
    * @description ModTest
    * @website https://www.cnblogs.com/doondo
    * @create 2021-04-19 15:11
    */
    public class ModTest {
    public static void main(String[] args) {
    System.out.println("7对3取余: " + 7%3 );
    System.out.println("7对3取模: " + Math.floorMod(7,3)); System.out.println("-7对-3取余: " + (-7) % (-3) );
    System.out.println("7对3取模: " + Math.floorMod(-7,-3));
    }
    }

    输出结果:

    7对3取余: 1
    7对3取模: 1
    -7对-3取余: -1
    7对3取模: -1
  • 当 x 和 y 的符号不同时,rem 函数结果的符号和 x 的一样,而 mod 和 y 一样

    package org.taoguoguo.hyper;
    
    /**
    * @author taoguoguo
    * @description ModTest
    * @website https://www.cnblogs.com/doondo
    * @create 2021-04-19 15:11
    * 取余运算结果的符号和 被除数 一致,取模运算结果的符号和 除数 一致
    * 取余,遵循尽可能让商向0靠近的原则
    * 取模,遵循尽可能让商向负无穷靠近的原则
    */
    public class ModTest {
    public static void main(String[] args) {
    System.out.println("7对-3取余: " + 7%(-3));
    System.out.println("7对-3取模: " + Math.floorMod(7,-3)); System.out.println("-7对3取余: " + -7%3);
    System.out.println("-7对3取模: " + Math.floorMod(-7,3));
    }
    }

    输出结果:

    7对-3取余: 1
    7对-3取模: -2
    -7对3取余: -1
    -7对3取模: 2

解析

1.符号相同时:	 7/3 = 2.3,产生了两个商2和3
7=3*2+1 或者 7=3*3+(-2)
结论: 7rem3=1 , 7mod3=1 2.符号不同时: 7/(-3)= -2.-3 产生了两个商-2和-3
7=(-3)*(-2)+1 或者 7=(-3)*(-3)+(-2)
结论: 7rem(-3)=1 , 7mod(-3)=(-2)

为什么遵循的是这样的原则?

在matlab中,关于取余和取模是这么定义的:

  • 当y≠0时:

    • 取余:rem(x,y)=x-y.*fix(x./y)
    • 取模:mod(x,y)=x-y.*floor(x./y)

    其中,fix()函数是向0取整,floor()函数是向负无穷取整

    以前边的运算为例:

    7/(-3)=-2.3,在这个运算中,x为7,y为-3,分别调用fix()和floor()两个函数,得到结果是:

    fix(-2.3)=-2

    floor(-2.3)=-3

    所以,rem(7,-3)=1,mod(7,-3)=-2

总结

  1. 取余,遵循尽可能让商向0靠近的原则,取模,遵循尽可能让商向负无穷靠近的原则
  2. 符号相同时,两者不会冲突;符号不同时,两者会产生冲突。
  3. 取余运算结果的符号和 被除数 一致,取模运算结果的符号和 除数 一致

Java取模和取余,你真的弄懂了吗?的更多相关文章

  1. C语言fmod()函数:对浮点数取模(求余)

    头文件:#include <math.h> fmod() 用来对浮点数进行取模(求余),其原型为:    double fmod (double x); 设返回值为 ret,那么 x = ...

  2. matlab取模与取余

    mod函数采用floor,rem函数采用fix函数.那么什么是floor和fix? fix(x):截尾取整.如: >> fix([3.4 , -3.4]) ans = 3 -3 floor ...

  3. POJ2635——The Embarrassed Cryptographer(高精度取模+筛选取素数)

    The Embarrassed Cryptographer DescriptionThe young and very promising cryptographer Odd Even has imp ...

  4. 取模性质,快速幂,快速乘,gcd和最小公倍数

    一.取模运算 取模(取余)运算法则: 1. (a+b)%p=(a%p+b%p)%p; 2.(a-b)%p=(a%p-b%p)%p; 3.(a*b)%p=(a%p * b%p)%p; 4.(a^b)%p ...

  5. fmod()函数 (对浮点数取模)

    头文件:#include <math.h> fmod() 用来对浮点数进行取模(求余),其原型为:    double fmod (double x); 设返回值为 ret,那么 x = ...

  6. C++负数类型转换,-1对256取模

    最近在读C++ primer的时候,发现p32上写道:当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数.因此,把-1赋值给8比特大小的unsigned c ...

  7. HDU1013,1163 ,2035九余数定理 快速幂取模

    1.HDU1013求一个positive integer的digital root,即不停的求数位和,直到数位和为一位数即为数根. 一开始,以为integer嘛,指整型就行吧= =(too young ...

  8. HPU 1471:又是斐波那契数列??(大数取模)

    1471: 又是斐波那契数列?? 时间限制: 1 Sec 内存限制: 128 MB 提交: 278 解决: 27 统计 题目描述 大家都知道斐波那契数列吧?斐波那契数列的定义是这样的: f0 = 0; ...

  9. 为什么对1e9 + 7取模

    在刷题的时候,很多题目答案都要求结果对1e9 + 7取模 刚开始我非常不理解,为什么要取模,取模难道结果不会变吗? 答案是结果会变,但因为原本需要得出的答案可能超出int64的范围,比如他叫你计算50 ...

  10. java中求余%与取模floorMod的区别

    初学java的时候接触的%这个符号 百分号? 求余? 取模? 我只知道不是百分号,好像是求余,听别人那叫求模运算符,跟求余一样,于是我便信了. 思考之后开始迷糊,然后经过多次考证得到以下结论. 首先, ...

随机推荐

  1. oeasy教您玩转vim - 85 - # 全局命令

    ​ "h", "b", "f", "d", "e", "a", "c& ...

  2. 番外篇: go语言写的简要数据同步工具

    go-etl工具 作为go-etl工具的作者,想要安利一下这个小巧的数据同步工具,它在同步百万级别的数据时表现极为优异,基本能在几分钟完成数据同步. 1.它能干什么的? go-etl是一个数据同步工具 ...

  3. java引入es使用

    引入依赖 <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>el ...

  4. Activity的创建

    Activity的创建: 1.layout内写入相关代码 此处为显示的页面 2.Java内创建相关类写入代码 3.在清单内写入 快捷方法:直接完成上面步骤 layout: match_parent// ...

  5. Jmeter函数助手12-threadNum

    threadNum函数用于获取当前线程编号.该函数没有参数,直接引用即可. 1.线程数可在组件[测试计划->线程组]设置.如下是不传入循环次数的${__threadNum}. "调试取 ...

  6. vue pinia sessionstorage 数据存储不上的原因

    vue pinia sessionstorage 的坑 默认的配置是开始 localStorage 如果用 sessionstorage 则发现数据存储不上 ,是因为缺少了序列化和反序列化 impor ...

  7. 【Front-End】获取视频资源

    需求场景: 我妈发个消息,在某某是网站上发现一个很好的视频,对我妈来说是一个有用的视频资源 但是视频网站不提供下载功能,叫我来帮她获取这个资源 一般来说可以利用一些东西来实现这个需求 这个是视频地址: ...

  8. 【Tutorial C】02 快速入门

    在信息化.智能化的世界里,可能很早很早 我们就听过许多IT类的名词, C语言也在其中,我们侃侃而谈,到底C程序是什么样子? 让我们先看简单的一个例子: #include<stdio.h> ...

  9. 【IDEA】DEBUG调试问题

    不要将断点打在方法的声明上: 会有一个菱形标志,在标记之后运行DEBUG模式会跑不起来 查看所有的断点标记: 在这里直接找到所有标记位置,弄掉就会跑起来了

  10. 强化学习算法:Learning to Learn: Meta-Critic Networks for Sample Efficient Learning

    地址: https://arxiv.org/pdf/1706.09529 作者提出了一种叫做Meta-Critic的框架,该框架可以用于强化学习.监督学习等算法中.该算法在强化学习中可以实现元强化学习 ...