关于除法,你也许觉得没什么值得谈论的,毕竟小学的时候体育老师就教过我们了。然而对于编程中使用的除法,我觉得还是有很多值得注意的细节的。为什么我想深究一下?因为我日常主要使用Java和Python编程,而它们的除法在细节上有很多不同之处,全是坑啊…所以接下来我也将着重于Java和Python,但是相信我,就算你不用Java和Python,也会有所收获的。

1.整数除法

对两个不能整除的整数做除法,就要面对舍入的问题。和大多数编程语言一样,Java的基本策略是向零取整(round to zero),也就是向绝对值变小的方向取整。举几个香甜的小栗子:3/2=1, -3/2=-1。而对于Python而言,情况就有所不同了。

全选复制放进笔记>>>-1/10

-1

显然如果按照Java的取整策略,-1/10应该得0,而Python给出的结果是-1。事实上Python的取整方式是向下取整,也就是向着数轴上负无穷的方向取整。

好吧,Java和Python的取整方式不同,夺大点事儿啊…那么如果我们要在Python下采用向零取整的结果,咋整?一种比较直接的方式是:

全选复制放进笔记>>>int(float(-1)/10)

0

2.取余

谁说没大事?( ̄▽ ̄)大事来了!

Java和Python整数除法都遵循下面这个公式:

全选复制放进笔记(a/b)*b+c=a

也就是说:

全选复制放进笔记a mod b=c=a-(a/b)*b

这里的/表示的是整数除法。既然它们的取整方式不一样,那么取余也会受到影响:

全选复制放进笔记For Java: -2 % 3==-2

For Python: -2 % 3==1

在某些实际应用中,我们可能会被要求得到一个整数的各位数字。如果输入的整数的正的,Java和Python都可以用相同的方法来解决:

全选复制放进笔记def func(a):

pos, res=1, []

while a/pos:

res+=(a/pos)%10,

pos*=10

return res

Java代码也差不多就是这样了。但如果输入的整数是一个负数,Java版本的代码还是可以得到正确的结果,而Python不能(曾经在这里被坑的,举手)。那怎样用Python正确地搞定这个问题嘞?可以先去绝对值和符号,当正数来处理,最后再在结果里搭上符号。

3. Follow-ups

3.1 Python中的另一个除法操作

我们知道,在Python中,基本的除号“/”是被重载了的。当两个操作数都是整数时,进行整数除法,得到整数结果,否则进行浮点数除法(真除法),得到浮点数结果。从Python 2.2开始,另一个除号被引入://,它只执行整数除法。注意,//的结果类型依操作数而定。

全选复制放进笔记>>>1.0/2

0.0

>>>1.0//2.0

0.0

>>>1//2

>0

另外,如果想同时得到商和余数,可以使用内建的函数divmod,结果是一个tuple。

全选复制放进笔记>>>divmod(7, 2)

(3, 1)

>>>divmod(7.0, 2)

(3.0, 1.0)

3.2 Python中的舍入

除了缺省的舍入方式,Python还有多种舍入可供选择。

Floor rounding:

全选复制放进笔记>>>import math

>>>math.floor(1.2)

1.0

>>>math.floor(-1.2)

-2.0

Ceiling rounding:

全选复制放进笔记>>>math.ceil(1.2)

2.0

>>>math.ceil(-1.2)

-1.0

Round-off:

全选复制放进笔记>>>round(0.5)

1.0

>>>round(-0.4)

-0.0

>>>round(-0.5)

-1.0

内嵌的round函数也可以一个指定保留小数位数的参数:

全选复制放进笔记>>>round(0.21, 1)

0.2

>>>round(0.21, 2)

0.21

Caution !

全选复制放进笔记>>>round(2.675, 2)

2.67

咦?bug啦?!当然不是。这里要明确一件事:计算机只认识0,1(量子计算机?懵)。就是说,我们输入的十进制数,在计算机内部都是用二进制来表示的。有的十进制数可以用二进制准确地表示出来,比如十进制的0.125可以表示为0b0.001;然而很多的小数是没法用二进制数精确表示的,计算机里存储的是它们的近似值,例如十进制的0.1,用二进制表示,可以近似为: 0b0.00011001100110011001100110011001100110011001100110011010,所以当我们把它换回十进制数以输出或者使用,得到的值就是0.1000000000000000055511151231257827021181583404541015625。也就是说,0.1在计算机里并不是刚好等于1/10的。你看:

全选复制放进笔记>>>0.1+0.2

0.30000000000000004

同样,当我们运行round()函数,也是对计算机中实际存储的值近似取舍。2.67实际上近似为2.67499999999999982236431605997495353221893310546875,第三位小数是4,那么round(2.675, 2)就相当于round(2.674, 2),结果当然是2.67。值得注意的是,这种现象是广泛存在于各种计算机和各种编程语言的,不是bug,只是有的语言选择了不让你看到。

3.3 Java中的舍入

Java提供了floor和ceil方法来实现向下和向上取整。

全选复制放进笔记Math.floor(2.9)

Math.ceil(2.1)

这俩函数简单方便,居家旅行必备。另外Java中也有个round函数,可以实现各种复杂的取整。

全选复制放进笔记System.out.println(Math.round(0.5));

//输出 1

System.out.println(Math.round(-0.5));

//输出 0

System.out.println(Math.round(-0.51));

//输出 -1

这什么鬼!Keep Calm and Carry On!

数学上有多种不同的策略来进行取整,比如我们体育老师教的四舍五入。各种取整策略的共同点就是要做真值作近似,那就会引入偏差。四舍五入显然并不是一种公平的策略(想想0~4的舍和5~9的得)。

有一个叫做银行家舍入(Banker’s Rounding)的东西,不造你听过没,反正我是最近才知道的。事实上.NET和VB6都是默认采用这种方式,而且IEEE 754默认采用这种Rounding。Banker’s Rounding 也就是round to even策略。

假设当前考虑那位的数字是d(其实d就是将不被保留的第一位),如果d<5,则舍(round to zero);如果d>5,则入(round away from zero);而当d==5时,就要根据d前后的数位来确定往哪边取了。

1) 如果d之后存在非零的数位,则入;

2)如果d之后不存在非零的数位,则看d之前的一个数位,用c表示:

a.如果c是奇数,则入;

b.如果c是偶数,则舍。

再来一把栗子,对下列数保留0位小数,

第一位小数就是d,整数位就是c:

BankRound(0.4)==0,  BankRound(0.6)==1,  BankRound(-0.4)==0,  BankRound(-0.6)==-1

BankRound(1.5)==2.0,  BankRound(-1.5)==-2.0,  BankRound(2.5)==2.0,  BankRound(-2.5)==-2.0

BankRound(1.51)==2.0,  BankRound(-1.51)==-2.0,  BankRound(2.51)==3.0,  BankRound(-2.51)==-3.0

可以看出,Banker’s Rounding对正数和负数的处理是对称的,因此不会引入符号带来的偏差。另外它以均等的几率来舍入数位(考虑c, c有各一半的几率为奇数和偶数),所以多次舍入后与真值的差别会较小。

扯了这么多,跟Java的Math.round( )有什么关系呢?我也是写到这才发现,好像没什么软(luan)关系。因为它并没有遵循Banker’s rounding。而是按照以下策略进行取整:

当考虑的数位d不是5,d<5就舍,d>5则入。

当d==5:

a.如果d的右边有非零数位,则入;

b.如果d的右边没有非零数位,则round to ceiling,即对负数舍,对正数入。

还有还有, 在Java里可以使用BigDecimal和RoundingMode实现更通用的取整方式。

全选复制放进笔记double d=-2.5;

BigDecimal bd=new BigDecimal(d);

double nd=bd.setScale(0,

RoundingMode.HALF_EVEN).doubleValue();

System.out.println(nd);

//输出 -2.0

setScale的第一个参数是保留的小数位数,第二个参数是舍入模式。可选的舍入模式有:

HALF_EVEN, 也就是银行家方式;

HALF_UP, 四舍五入;

HALF_DOWN, 五舍六入;

CEILING、FLOOR, 向正无穷、负无穷方向;

UP、DOWN*, 向零和远离零;

UNNECESSARY, 断言舍入后的值和原值相等,也就是不需要舍入。如果断言错了,抛出ArithmeticException异常。

先写到这,比较粗糙,但是希望你有所收获吧。欢迎讨论,有话好好说( ̄▽ ̄)

转载请注明:作者曾会玩

python除法编程_Java和Python中的整数除法,取余,舍入相关推荐

  1. java 斐波那契编程_Java实现Fibonacci(斐波那契)取余的示例代码

    Java实现Fibonacci(斐波那契)取余的示例代码 发布时间:2020-10-09 06:05:36 来源:脚本之家 阅读:78 作者:南墙 Description Fibonacci数列的递推 ...

  2. Python语言编程学习:numpy中的array格式数据切片与pandas中的dataframe格式数据切片、相互转换

    Python语言编程学习:numpy中的array格式数据切片与pandas中的dataframe格式数据切片.相互转换 目录 numpy中的array格式数据切片与pandas中的dataframe ...

  3. python语言的取余运算符_Python 中用于整数除法取余的运算符是()_学小易找答案...

    [填空题]隐球菌病多由()传播. [单选题]下列选项中,哪一个符号是管道符号. ( ) [多选题]可采用分批法计算产品成本的企业有( ) [填空题]现有字符串 s="1234567" ...

  4. 《Python计算机视觉编程》一书中关于增强现实茶壶显示的程序

    大家好,我是第一次写CSDN博客,也是刚开始学习用Python进行计算机视觉编程,有很多不懂和不足的地方,希望大家多包涵.以下纯粹是我个人的一些实际操作经历. 在<Python计算机视觉编程&g ...

  5. python代码编程教学入门,python代码编程火影忍者

    python源代码编程软件 编写python源代码的软件.首推的Pycharm. PyCharm用于bai一般IDE具备的功能,比如, 调试.语法高亮.Project管理.du代码跳转.智能提示.自动 ...

  6. C语言基础课 编写程序之1.百元买鸡,公鸡一只5元,母鸡一只3元,小鸡3只一元,现将一百元要买一百只鸡,公鸡母鸡小鸡各多少只2.编程求1~200中能被2除余1或能被3除余1或能被5除余1的前10个整数

    1.拿百元买鸡问题.公鸡一只5元,母鸡一只3元,小鸡3只一元,现将一百元要买一百只鸡,请问一百只鸡中公鸡,母鸡,小鸡各多少只 #include<stdio.h> int main() {i ...

  7. python课程编程题汇总(中)

    python编程题汇总 众所周知,由于疫情的原因,大家都在上网课,我也不例外啦~ 用这个贴子来记录也和大家分享一下我们课上的编程讨论题 上篇在这→python课程编程题汇总(上) 下篇在这→pytho ...

  8. python机器人编程——在VREP环境中,UARM与摄像头联动,实现基于视觉识别的自动抓取,垃圾自动分类(上)

    目录 前言 在VREP中加入视觉传感,用python侧获取图像 在VREP中布置垃圾分类场景 Step1:用三维软件造模型 Step2:导入到vrep Step3:关联shap.调整位置及贴图 测试一 ...

  9. python快速编程入门例题-Python快速编程入门,打牢基础必须知道的11个知识点 !...

    Python被誉为全世界高效的编程语言,同时也被称作是"胶水语言",那它为何能如此受欢迎,下面我们就来说说Python入门学习的必备11个知识点,也就是它为何能够如此受欢迎的原因. ...

最新文章

  1. 公司用--页面表单提交用的key是拼接的,保存时action的写法,struts1
  2. 用PHP代码实现简单的工厂模式,用PHP代码实现简单的工厂模式
  3. Python网络编程—(TCP、UDP区别)
  4. Jerry 的 SAP 技术交流群里讨论的技术问题都会同步到这个帖子里
  5. 18_python基础—面向对象-多态
  6. delphi switch语句例子_Python系列之常用语句
  7. 金电联行程小龙:企业数字化转型的目标、决策与实践
  8. 【学习】03 淘宝爬虫-使用selenium采集关键词为电动车的数据
  9. mysql清除内存不足_MySQL内存不足怎么办
  10. 如何读取H264文件获得每一帧的数据(VsParserPro)
  11. 24 Hour Wallpaper for Mac(动态桌面壁纸软件)
  12. Vin码车架号识别技术已经很成熟了
  13. php checkbox默认选择问题,PHP_php select,radio和checkbox默认选择的实现方法,这是扩展yibing的select默认选择 - phpStudy...
  14. Android APP签名找回终极版
  15. 查找父类的所有子类 crtl+alt+b
  16. SCRAPY爬虫实例
  17. 在spring.io网下下载的快速入门项目,导进去pom.xml文件爆红,报:Non-resolvable parent POM for com.tc:demo:0.0.1-SNAPSHOT: F
  18. 香港电视剧的配音怎么都是一个腔调的呢?
  19. 当今商务中的礼仪(上)
  20. 台湾D-Link全景安全公司证书被盗,且被APT组织blacktech利用

热门文章

  1. android仿36氪轮播,仿36氪(附源代码)
  2. ​LeetCode刷题实战216:组合总和 III
  3. 挥一挥衣袖,开始一段新的旅程
  4. fiddler监控手机请求 1
  5. 终于搞定Mac下无线网卡安装不了的问题
  6. 搭建简单的Netty开发环境
  7. 解决stackoverflow打开慢的问题
  8. DDD兴起的原因,以及与微服务的关系
  9. py3 BeautifulSoup 利器 html 解析器使用
  10. php如何转换音频格式,音频格式如何在线转换,音频转换软件