年年有余之java求余的技巧集合

背景

  传说里玉皇大帝派龙王马上降雨到共光一带,龙王接到玉皇大帝命令,立马从海上调水,跑去共光施云布雨,但粗心又着急的龙王不小心把海里的鲸鱼随着雨水一起降落在了共光,龙王怕玉皇大帝责怪,灵机一动便声称他是派鱼到共光,希望百姓可以年年有余,并请求玉皇大帝将这条鱼任命为鱼神,保佑人间太平可以年年有余。

                                      年年有余

java 求余操作初阶

java中也有余的规范【jls-15.17.3】,废话不说,直接上代码,从中我们可以学到很多技巧:

例1:

        int a = 5%3; // 2
        int b = 5/3; // 1
        System.out.println("5%3 produces " + a +" (note that 5/3 produces " + b + ")");

相信大多数人都知道结果了:

          5%3 produces 2 (note that 5/3 produces 1)

java 求余操作中阶

我们知道,正数不仅仅有正整数还有负整数,那么负数的情况下,会出现什么变化呢?

例2:

        int c = 5%(-3); // 2
        int d = 5/(-3); // -1
        System.out.println("5%(-3) produces " + c +" (note that 5/(-3) produces " + d + ")");
        int e = (-5)%3; // -2
        int f = (-5)/3; // -1
        System.out.println("(-5)%3 produces " + e +" (note that (-5)/3 produces " + f + ")");
        int g = (-5)%(-3); // -2
        int h = (-5)/(-3); // 1
        System.out.println("(-5)%(-3) produces " + g +" (note that (-5)/(-3) produces " + h + ")");

能完全正确得到结果的就很少了吧?

          5%(-3) produces 2 (note that 5/(-3) produces -1)
          (-5)%3 produces -2 (note that (-5)/3 produces -1)
          (-5)%(-3) produces -2 (note that (-5)/(-3) produces 1)

为什么求余的结果是这样的呢?jls-15.17.3规范告诉我们:

The binary % operator is said to yield the remainder of its operands from an implied division; the left-hand operand is the dividend and the right-hand operand is the divisor.
It follows from this rule that the result of the remainder operation can be negative only if the dividend is negative, and can be positive only if the dividend is positive. Moreover, the magnitude of the result is always less than the magnitude of the divisor.

注意:求余的正负数给dividend(左边操作数)的符号位一致!

java 求余操作高阶

java求余操作不但支持整数还支持浮点数

class Test2 {
 public static void main(String[] args) {
 double a = 5.0%3.0; // 2.0
 System.out.println("5.0%3.0 produces " + a);
 double b = 5.0%(-3.0); // 2.0
 System.out.println("5.0%(-3.0) produces " + b);
 double c = (-5.0)%3.0; // -2.0
 System.out.println("(-5.0)%3.0 produces " + c);
 double d = (-5.0)%(-3.0); // -2.0
 System.out.println("(-5.0)%(-3.0) produces " + d);
 }
}

相信很多人可以根据整型的规则,得出正确的结果

5.0%3.0 produces 2.0
5.0%(-3.0) produces 2.0
(-5.0)%3.0 produces -2.0
(-5.0)%(-3.0) produces -2.0

补充一下,浮点型的求余有一些特殊的规则:

The result of a floating-point remainder operation as computed by the % operator is not the same as that produced by the remainder operation defined by IEEE 754. The IEEE 754 remainder operation computes the remainder from a rounding division, not a truncating division, and so its behavior is not analogous to that of the usual integer remainder operator. Instead, the Java programming language defines % on floating-point operations to behave in a manner analogous to that of the integer remainder operator; this may be compared with the C library function fmod. The IEEE 754 remainder operation may be computed by the library routine Math.IEEEremainder.

The result of a floating-point remainder operation is determined by the rules of IEEE 754 arithmetic:

If either operand is NaN, the result is NaN.
If the result is not NaN, the sign of the result equals the sign of the dividend.
If the dividend is an infinity, or the divisor is a zero, or both, the result is NaN.
If the dividend is finite and the divisor is an infinity, the result equals the dividend.
If the dividend is a zero and the divisor is finite, the result equals the dividend.
In the remaining cases, where neither an infinity, nor a zero, nor NaN is involved, the floating-point remainder r from the division of a dividend n by a divisor d is defined by the mathematical relation r = n - (d ⋅ q) where q is an integer that is negative only if n/d is negative and positive only if n/d is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true mathematical quotient of n and d.
Evaluation of a floating-point remainder operator % never throws a run-time exception, even if the right-hand operand is zero. Overflow, underflow, or loss of precision cannot occur.

java 求余操作骨灰级

学到这里,或许有人沾沾自喜,我都掌握了求余的所有规则,看来需要给你泼泼冷水:

    public static void main(String[] args) {
        final int MODULUS = 3;
        int[] histogram = new int[MODULUS];
        // Iterate over all ints (Idiom from Puzzle 26)
        int i = Integer.MIN_VALUE;
        do {
        histogram[Math.abs(i) % MODULUS]++;
        } while (i++ != Integer.MAX_VALUE);
        for (int j = 0; j < MODULUS; j++)
        System.out.println(histogram[j] + " ");
    }

这个程序会打印什么?有人经过繁琐复杂的算出一个结果:

1431655765 1431655766 1431655765

但其实,上述程序运行报错:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2
    at com.java.puzzlers.ModTest.main(ModTest.java:11)

为什么数组会出现索引 -2?奇怪吧?要回答这个问题,我们必须要去看看Math.abs 的文档

 /**
 * Returns the absolute value of an {@code int} value.
 * If the argument is not negative, the argument is returned.
 * If the argument is negative, the negation of the argument is returned.
 *
 * <p>Note that if the argument is equal to the value of
 * {@link Integer#MIN_VALUE}, the most negative representable
 * {@code int} value, the result is that same value, which is
 * negative.
 *
 * @param a the argument whose absolute value is to be determined
 * @return the absolute value of the argument.
 */
 public static int abs(int a) {
 return (a < 0) ? -a : a;
 }
特意说明,如果是Integer#MIN_VALUE,返回负数

java里有很多小技巧,需要我们勤翻api和jsl,多学习多练习。

参考资料:

【1】https://baike.baidu.com/item/%E5%B9%B4%E5%B9%B4%E6%9C%89%E4%BD%99/7625174?fr=aladdin

【2】https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.17.3

【3】java解惑

原文地址:https://www.cnblogs.com/davidwang456/p/11577326.html

时间: 2024-10-03 14:41:54

年年有余之java求余的技巧集合的相关文章

java学习日记-基础-随机数组的求余运算

时间是2017年5月6日,青年节刚过,坐标上海,沪漂2个月. 就这样简短地开始吧.                                by:slowcity [案例分析1] 要求定义一个int 型数组a,包含100 个元素,保存100个随机的4 位数.再定义一个int 型数组b,包含10 个元素.统计a 数组中的元素对10 求余等于0 的个数,保存到 b[0]中:对10 求余等于1 的个数,保存到b[1]中,--依此类推 一般看到这类的最基本的思路:1先建立一个含数组存随机四位数 2

关于大整数的加减乘除求余运算 java

自己用java 实现了大字符串整数的加减乘除和求余运算, 加减法的算法是模拟手工笔算的计算过程, 除法就是从最高位不停的减操作, 乘法的算法 :遍历一个数的各个位数以及他所在位置,另一个数根据这个数的位置末位添n个0,然后累加次数为这个位置数的数值 原创代码如下: public class Demo6 { public static void main(String[]args){ System.out.println(add("-989","989")); Sys

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

初学java的时候接触的%这个符号 百分号? 求余? 取模? 我只知道不是百分号,好像是求余,听别人那叫求模运算符,跟求余一样,于是我便信了. 思考之后开始迷糊,然后经过多次考证得到以下结论. 首先,%是求余的意思,不是求模的意思.求模不完全等于求余. 首先我们遵守公式: a = b * q + r; 这里的a是被除数,b是除数,q是商,r是余数也可以是模. q= a/b 且 |r| < |b| 于是得到: r = a – (a/b)*b; r的求值公式都是这样,那么求余和求模的区别在哪呢? 1

求余运算符

笔记摘自<极客学院> 求余运算(a % b)是计算b的多少倍刚刚好可以容入a,返回多出来的那部分(余数). 注意:求余运算(%)在其他语言也叫取模运算.然而严格说来,我们看该运算符对负数的操作结果,"求余"比"取模"更合适些. 我们来谈谈取余是怎么回事,计算9 % 4,你先计算出4的多少倍会刚好可以容入9中: 2倍,非常好,那余数是1(用橙色标出) 在 Swift 中可以表达为: 9 % 4 // 等于 1 为了得到a % b的结果,%计算了以下等式,并

BigDecimal求余操作

BigDecimal求余操作如下: package com.qiu.lin.he; import java.math.BigDecimal; public class CeShi { public static void main(String[] args) { BigDecimal bg = BigDecimal.valueOf(11); BigDecimal om2 = BigDecimal.valueOf(25); System.out.println(om2.divideAndRema

实数范围内的求模(求余)运算:负数求余究竟怎么求

背景 最近在一道 Java 习题中,看到这样的一道题: What is the output when this statement executed: System.out.printf(-7 % 3); 正整数的取余运算大家都很熟悉,但是对于负数.实数的取余运算,确实给人很新鲜的感觉.于是我对此进行了一些探索.我发现,这里面还是颇有一点可以探索的东西的. 探究 首先,看看自然数的取模运算(定义1): 如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = qd 

Java代码性能优化技巧

流方面: private FileOutputStream writer; writer = new FileOoutputStream(fileName); 使用BufferedOutputStream 对写入FileOutputStream的数据进行缓存 //将writer的类型由FileOutputStream 变更为BufferedOutputStream //private FileOutputStream writer; private BufferedOutputStream wr

取模和求余的区别

通常情况下取模运算(mod)和求余(rem)运算被混为一谈,因为在大多数的编程语言里,都用'%'符号表示取模或者求余运算.在这里要提醒大家要十分注意当前环境下'%'运算符的具体意义,因为在有负数存在的情况下,两者的结果是不一样的. 对于整型数a,b来说,取模运算或者求余运算的方法都是: 1.求 整数商: c = a/b; 2.计算模或者余数: r = a - c*b. 求模运算和求余运算在第一步不同: 取模求余运算在取c的值时,向0 方向舍入(fix()函数): 而求余取模运算在计算c的值时,向

Java程序性能优化技巧

多线程.集合.网络编程.内存优化.缓冲..spring.设计模式.软件工程.编程思想 1.生成对象时,合理分配空间和大小new ArrayList(100); 2.优化for循环Vector vect = new Vector(1000);for( inti=0; i<vect.size(); i++){ ...}for循环部分改写成:int size = vect.size();for( int i=0; i>size; i++){ ...} 如果size=1000,就可以减少1000次si