(注意:与另一个问题不同,因为OP从未明确指定向0或-Infinity舍入)

JLS 15.17.2表示整数除法向零舍入。 如果我想要正除数的floor()行为(我不在乎负除数的行为),最简单的方法是在数字上对所有输入都正确?

int ifloor(int n, int d)

{

/* returns q such that n = d*q + r where 0 <= r < d

* for all integer n, d where d > 0

*

* d = 0 should have the same behavior as `n/d`

*

* nice-to-have behaviors for d < 0:

*   option (a). same as above:

*     returns q such that n = d*q + r where 0 <= r < -d

*   option (b). rounds towards +infinity:

*     returns q such that n = d*q + r where d < r <= 0

*/

}

long lfloor(long n, long d)

{

/* same behavior as ifloor, except for long integers */

}

(更新:我想同时为int和long算术提供一种解决方案。)

这必须是重复的,但是我找不到它,如果不是重复的,那么我完全感到惊讶的是,经过3年以上的StackOverflow之后,它还没有出现。

在其余的d < 0条件下,我认为您有几个颠倒的符号。 看起来您想要选项(a)为0 <= r < -d,选项(b)为d < r <= 0。

正确:谢谢,我的意思是正数除数。 (它本应向+ infinity舍入)

如果可以使用第三方库,则Guava具有以下内容:IntMath.divide(int, int, RoundingMode.FLOOR)和LongMath.divide(int, int, RoundingMode.FLOOR)。 (公开:我为番石榴做出了贡献。)

如果您不想为此使用第三方库,则仍然可以查看实现。

多数民众赞成在听到-番石榴是一个非常有名的图书馆。

番石榴为什么没有包含双打除法功能?

@voipp:你甚至会怎么做?它与正常的双分割有何不同?

没有。你显然是对的

当n < 0和d > 0时,有一个相当简洁的公式可以使用:取n的按位补码,进行除法,然后取结果的按位补码。

int ifloordiv(int n, int d)

{

if (n >= 0)

return n / d;

else

return ~(~n / d);

}

对于其余部分,进行类似的构造(在满足通常不变式ifloordiv(n, d) * d + ifloormod(n, d) == n的意义上与ifloordiv兼容)得出的结果始终在[0, d)范围内。

int ifloormod(int n, int d)

{

if (n >= 0)

return n % d;

else

return d + ~(~n % d);

}

对于负除数,公式并不是那么整洁。这是ifloordiv和ifloormod的扩展版本,它们遵循负除数的" nice-to-have"行为选项(b)。

int ifloordiv(int n, int d)

{

if (d >= 0)

return n >= 0 ? n / d : ~(~n / d);

else

return n <= 0 ? n / d : (n - 1) / d - 1;

}

int ifloormod(int n, int d)

{

if (d >= 0)

return n >= 0 ? n % d : d + ~(~n % d);

else

return n <= 0 ? n % d : d + 1 + (n - 1) % d;

}

对于d < 0,当d == -1和n为Integer.MIN_VALUE时,存在不可避免的问题,因为这样数学结果就会溢出类型。在这种情况下,就像常规的Java部门一样,上面的公式返回包装的结果。据我所知,这是唯一一个默默地得到"错误"结果的极端情况。

@trutheality:加,我是个白痴!谢谢;将立即解决此问题!

@trutheality:是的,除了结果仍然以MIN_VALUE的形式出现外,这在数学上是错误的(但是对2 ** 取模是正确的,所以这足够好了)。我很讨厌在d < 0中潜伏着其他极端情况,但没有花时间弄清楚它们到底是什么。也许我应该那样做。

呵呵,事实证明我并不知道除法实际上会溢出。

@trutheality:我编辑了最后一段;好点?据我所知,这种情况确实是唯一的极端情况。

是的,现在非常清楚。

(由于int的答案是相同的,所以我正在为long做所有事情,只需将int替换为每个long,将Integer替换为每个long。)

您可以Math.floor双除法结果,否则...

原始答案:

return n/d - ( ( n % d != 0 ) && ( (n<0) ^ (d<0) ) ? 1 : 0 );

优化答案:

public static long lfloordiv( long n, long d ) {

long q = n/d;

if( q*d == n ) return q;

return q - ((n^d) >>> (Long.SIZE-1));

}

(为完整起见,也可以将BigDecimal与ROUND_FLOOR舍入模式一起使用。)

新编辑:现在,我只是想看看它可以优化多远的乐趣。到目前为止,使用Mark的答案是最好的:

public static long lfloordiv2( long n, long d ){

if( d >= 0 ){

n = -n;

d = -d;

}

long tweak = (n >>> (Long.SIZE-1) ) - 1;

return (n + tweak) / d + tweak;

}

(使用比上述方法便宜的操作,但字节码略长(29 vs. 26))。

请不要把我引向Math.floor。如果它恰好对int变量有效(我不确定),则由于缺乏精度,它对long变量无效。

我会在一分钟后走出门,但如果我能在星期一抽查它的正确性,则病+1。谢谢+周末愉快。

真好!一个简单的混淆优化:将(n<0) ^ (d<0)替换为n^d < 0。编译器可能会为您进行优化,但是我对此表示怀疑。

埃德:当心:n * d可能在溢??出时产生不正确的结果。

@JasonS多数民众赞成在XOR(^)而不是*。

第二种解决方案是错误的。如果n是-3,并且d是2,则该函数输出-1(不正确)。

@LouisWasserman不错的收获,那就是我尝试不进行微优化而得到的...

return BigDecimal.valueOf(n).divide(BigDecimal.valueOf(d), RoundingMode.FLOOR).longValue();

java infinity 处理_关于math:Java:如何执行整数除法,舍入为-Infinity而不是0?相关推荐

  1. java 字符串乱码_这份Java面试题含答案解析竟然真的让你不用在面试上“如履薄冰”...

    面试题集共分为以下十部分: 一.Core Java: 1 - 95 题1 - 24 页 基础及语法: 1 - 61 题1 - 13 页 异常: 62 - 69 题13 - 15 页 集合: 70 - ...

  2. java web 截图_如何以Java实现网页截图技术

    今天看到某网友关于"如何以Java实现网页截图技术"的咨询帖,由于出现该咨询的地点非常不适合较长回复,故以博文形式回答. 事实上,如果您想以Java实现网页截图,也就是" ...

  3. java 异常机制_深入理解Java异常处理机制

    一.引子 try-catch-finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解.不过,我亲自体验的"教训"告诉我,这个东西可不是想象中 ...

  4. java 进度条_进度条Java

    你必须使用线程.设计一个实现Runnable接口的类,它将更新这样的值. class ProgressBarUpdator implements java.lang.Runnable { /** * ...

  5. 00005在java结果输出_浅谈Java反序列化漏洞原理(案例未完善后续补充)

    摘要: 0005,这个16进制流基本上也意味者java反序列化的开始:(2)HTTP:必有rO0AB,其实这就是aced0005的base64编码的结果:以上意味着存在Java反序列化,可尝试构造pa ...

  6. java廖雪峰_廖雪峰Java教程学习笔记(一)——Java程序基础

    (一)Java程序基本结构 Java是面向对象的语言,一个程序的基本单位就是class.在class内部,可定义若干方法. 类名要求: 类名必须以英文字母开头,后接字母,数字和下划线的组合 习惯以大写 ...

  7. 马士兵 java 学习笔记_马士兵java教程笔记1

    ---恢复内容开始--- 前记 虽然已经是个研究生了,但是会的东西还是特别的少 甚至连java都不能说是很会 所以准备从现在开始能好好的学习java 变成java master 标识符 标识符是由字母 ...

  8. java 02-cf_cf活动如何设置java环境变量_如何设置java环境变量

    cf助手怎么连接wifi_连接无线网设置 对于刚刚学习java的win7用户来说,首先要学会安装jdk和配置java环境变量,这是学习java的唯一途径,否则编写的代码运行时会出现bug.关于这一点, ...

  9. java多线程面试_面试之JAVA多线程

    1如何创建线程 创建多线程实现类MyThread extends Thread,继承Thread后重载run()方法,在调用类中创建对象后调用start()方法执行该线程. 创建实现类MyThread ...

最新文章

  1. 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制
  2. CVPR2020 | 反传统的无监督人脸旋转方案:旋转-渲染
  3. 如何实现拼音与汉字的互相转换
  4. bzoj3122 [Sdoi2013]随机数生成器(bsgs+扩欧+数列)
  5. 电商系统下单时商品库存和销售状态如何处理
  6. python作用域的理解-理解Python的UnboundLocalError(Python的作用域)
  7. 苹果将允许iPhone直接使用NFC接受信用卡付款
  8. Espcms 注册或登录提示Can not connect to MySQL server
  9. 软件行业渠道的价值在哪里?
  10. JAVA给banking作界面_银行运行模拟编程 求助!!!
  11. 安装redis 5.0.5版本 真香警告
  12. julia: 如何序列化和反序列化?
  13. 一个纸水杯的测试用例设计。
  14. Java动态代理二——CGLIB动态代理应用
  15. vi编辑文件时如何批量替换字符串
  16. Excel表格自动填充、批量提取与组合数据
  17. 设置div背景透明的方法
  18. SAP ABAP MOVE-CORRESPONDING ... TO ...的使用
  19. 只知道努力工作的人,失去了赚钱的机会,过去是适者生存,现在是强者生存,沉思你将来会怎样?
  20. 干货课堂丨分享一种LCD驱动电路方案【飞凌嵌入式】

热门文章

  1. Pulsar简介及Pulsar部署、原理和使用介绍
  2. 22. 处理Excel文件-删除在其他文件中存在的记录
  3. 我的 2019:找工作 | 写作 | 挣钱,文末送年终福利
  4. 弘辽科技:淘宝关键词权重该如何提升?商家要记住的4大必要因素
  5. 全球与中国静注人免疫球蛋白市场深度研究分析报告
  6. “码上看房”,扫二维码线上实景观看房屋
  7. JAVA 错误: 在类 com.runoob.test.HelloWord 中找不到 main 方法, 请将 main 方法定义为: public static void main(String
  8. flacs 安装教程_改良人工晶体安装方法在FLACS中的应用研究
  9. 支持AMP的PHP网站程序,AMP(Apache+Mysql+PHP)的安装与配置
  10. Mac启动Tomcat