• 取模:

  1. 转载自:http://ceeji.net/blog/mod-in-real/

 背景

 最近在一道 Java 习题中,看到这样的一道题:

 What is the output when this statement executed:
System.out.printf(- % ); 正整数的取余运算大家都很熟悉,但是对于负数、实数的取余运算,确实给人很新鲜的感觉。于是我对此进行了一些探索。我发现,这里面还是颇有一点可以探索的东西的。 探究 首先,看看自然数的取模运算(定义1): 如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = qd + r 且0 ≤ r < d。其中,q 被称为商,r 被称为余数。 那么对于负数,是否可以沿用这样的定义呢?我们发现,假如我们按照正数求余的规则求 (-) mod 的结果,就可以表示 - 为 (-)* +。其中,2是余数,-3是商。 那么,各种编程语言和计算器是否是按照这样理解的呢?下面是几种软件中对此的理解。 语言 语句 输出
C++(G++ 编译) cout << (-) % ; -
Java(1.6) System.out.println((-) % ); -
Python 2.6 (-) %
百度计算器 (-) mod
Google 计算器 (-) mod
可以看到,结果特别有意思。这个问题是百家争鸣的。看来我们不能直接把正数的法则加在负数上。实际上,在整数范围内,自然数的求余法则并不被很多人所接受,大家大多认可的是下面的这个定义2。 如果a 与d 是整数,d 非零,那么余数 r 满足这样的关系: a = qd + r , q 为整数,且0 ≤ |r| < |d|。 可以看到,这个定义导致了有负数的求余并不是我们想象的那么简单,比如,- 和 都是 (-) mod 正确的结果,因为这两个数都符合定义。这种情况下,对于取模运算,可能有两个数都可以符合要求。我们把 - 和 分别叫做正余数和负余数。通常,当除以d 时,如果正余数为r1,负余数为r2,那么有 r1 = r2 + d 对负数余数不明确的定义可能导致严重的计算问题,对于处理关键任务的系统,错误的选择会导致严重的后果。 看完了 (-) mod ,下面我们来看一看 mod (-) 的情况(看清楚,前面是 带负号,现在是 带负号)。根据定义2, = (-) * (-) + 或7 = (-) * (-) -,所以余数为 或 -。 语言 语句 输出
C++(G++ 编译) cout << % (-);
Java(1.6) System.out.println( % (-));
Python 2.6 % (-) -
百度计算器 mod (-) -
Google 计算器 mod (-) -
从中我们看到几个很有意思的现象: Java 紧随 C++ 的步伐,而 Python、Google、百度步调一致。难道真是物以类聚?联想一下,Google 一直支持 Python,Python 也颇有 Web 特色的感觉,而且 Google Application Engine 也用的 Python,国内的搜索引擎也不约而同地按照 Google 的定义进行运算。
可以推断,C++ 和 Java 通常会尽量让商更大一些。比如在 (-) mod 3中,他们以 - 为商,余数为 -。在 Python 和 Google 计算器中,尽量让商更小,所以以 - 为商。在 mod (-) 中效果相同:C++ 选择了 作为商,Python 选择了 作为商。但是在正整数运算中,所有语言和计算器都遵循了尽量让商小的原则,因此 mod 结果为 不存在争议,不会有人说它的余数是-。
如果按照第二点的推断,我们测试一下 (-) mod (-),结果应该是前一组语言(C++,Java)返回 ,后一组返回 -。(请注意这只是假设)
于是我做了实际测试: 语言 语句 输出
C++(G++ 编译) cout << - % (-); -
Java(1.6) System.out.println(- % (-)); -
Python 2.6 - % (-) -
百度计算器 - mod (-) -
Google 计算器 - mod (-) -
结果让人大跌眼镜,所有语言和计算机返回结果完全一致。 总结 我们由此可以总结出下面两个结论: 对于任何同号的两个整数,其取余结果没有争议,所有语言的运算原则都是使商尽可能小。
对于异号的两个整数,C++/Java语言的原则是使商尽可能大,很多新型语言和网页计算器的原则是使商尽可能小。
拓展 最后是拓展时间。对于实数,我们也可以定义取模运算(定义3)。 当 a 和 d 是实数,且d 非零, a 除以 d 会得到另一个实数(商),没有所谓的剩余的数。但如果要求商为一个整数,则余数的概念还是有必要的。可以证明:存在唯一的整数商 q 和唯一的实数 r 使得: a = qd + r, ≤ r < |d|. (转自维基百科) 如上在实数范围内扩展余数的定义在数学理论中并不重要,尽管如此,很多程序语言都实现了这个定义。至于哪些程序语言实现了这个定义,就留给大家自己探究吧!

  

  2. 5%7=5   4%9=4

    小数除大数商0余本身

  • while后如果没有花括号"{" "}",则默认紧跟着while的那一句是循环体。
  • TJU 小号:tjuacm2015

C++ 备忘录 (1)的更多相关文章

  1. MementoPattern(备忘录模式)

    /** * 备忘录模式 * @author TMAC-J * 用于存储bean的状态 */ public class MementoPattern { public class Memento{ pr ...

  2. C#设计模式-备忘录模式

    访问者模式的实现是把作用于某种数据结构上的操作封装到访问者中,使得操作和数据结构隔离.而本文要介绍的备忘者模式与命令模式有点相似,不同的是,命令模式保存的是发起人的具体命令(命令对应的是行为),而备忘 ...

  3. Vuex2.0+Vue2.0构建备忘录应用实践

    一.介绍Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,适合于构建中大型单页应用. ...

  4. 设计模式03备忘录(java)

    先贴代码有空来写内容. 备忘录1 //简单的备忘录,只可以记录上一次修改前的状态,实现撤回一次的操作. class Student{ private String name; private Stri ...

  5. C#设计模式系列:备忘录模式(Memento)

    1.备忘录模式简介 1.1>.定义 备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可以将该对象恢复到原先保存的状态. 1.2>.使用频率 ...

  6. php实现设计模式之 备忘录模式

    <?php /*备忘录模式:在不破坏封装的前提下,获取对象的内部状态,并且在对象外保存该状态.这样就可以将该对象恢复到保存之前的状态(行为模式) * * 发起人:记录当前时刻的内部状态,负责定义 ...

  7. 十一个行为模式之备忘录模式(Memento Pattern)

    定义: 在不破坏原有封装的情况下,捕获一个对象的内部状态,并在对象之外保存.当对象出错或者无效是,可以根据该备忘录进行恢复. 结构图: Originator:原发类,被记录的对象,包含若干内部状态.一 ...

  8. 自适应备忘录 demo

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  9. java设计模式之备忘录模式

    备忘录模式 备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.一听到备忘录这个字的时候想起了小小时打的游 ...

  10. 备忘录模式(Memento Pattern)

    在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 备忘录模式主要思想是——利用备忘录对象来对保存发起人的内部状态,当发起人需要恢复原 ...

随机推荐

  1. R6

    RC 的加强版是 R6 , R6 是一个扩展包,能够实现支持公共和私有字段与方法的更有效的引用类,还有一些其他强大的功能.运行以下代码安装这个包:install.packages("R6&q ...

  2. c++ primer plus 第三章 课后题答案

    #include<iostream> using namespace std; int main() { ; int shen_gao; cout <<"Please ...

  3. windows下的mongodb安装(真垃圾)

    一.下载 3.6下载安装会卡死.只能下3.4的.http://downloads.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-v3.4-la ...

  4. Codeforces 888E - Maximum Subsequence(折半枚举(meet-in-the-middle))

    888E - Maximum Subsequence 思路:折半枚举. 代码: #include<bits/stdc++.h> using namespace std; #define l ...

  5. 使用 Python 的 Socket 模块构建一个 UDP 扫描工具

    译文:oschina 英文:bt3gl 当涉及到对一些目标网络的侦察时,出发点无疑是首先发现宿主主机.这个任务还可能包含嗅探和解析网络中数据包的能力. 几周前,我曾经谈到了如何使用Wireshark来 ...

  6. Linux中查看各文件夹大小(扫盘)

    df -h ./ du -hs ./ du -h /ifs4/BC_RD/USER/lizhixin/my_project/human_chr22 | grep [[:digit:]+]G du [- ...

  7. 使用Jenkins实现maven项目一键部署

    下面的博客请详细的,值得一看:jenkins+maven+svn实现简单的一键发布 http://blog.csdn.net/pein_zero/article/details/52597615#co ...

  8. CF576E Painting Edges

    首先,有一个很暴力的nk的做法,就是对每种颜色分别开棵lct来维护. 实际上,有复杂度与k无关的做法. 感觉和bzoj4025二分图那个题的区别就在于这个题是边dfs线段树边拆分区间.

  9. spring AOP自定义注解 实现日志管理

    今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...

  10. jconsole工具使用----jvm内存泄漏问题

    转载地址:https://www.cnblogs.com/baihuitestsoftware/articles/6405580.html Jconsole,Java Monitoring and M ...