在不使用条件语句的情况下找出三个随机生成数字中的最高、第二高和最低

Find the highest, second highest, and lowest of three random generated numbers without using conditional statements

作为大学 IT 专业的一年级学生,我有一个 Java 作业,我必须显示三个随机生成的数字并将它们排序为最高、第二高、最低。我们教授给的挑战是不使用任何条件语句或数组。

代码如下:

import java.text.DecimalFormat;
import java.util.Scanner;
import java.util.Random;
public class Main {
  public static void main(String[] args) {
    DecimalFormat dcf = new DecimalFormat("0.00");
    Scanner sc = new Scanner(System.in);
    Random rand = new Random();
    int high, low, totnum;
    double NumAvr;
    
    high = 100;
    low = 1; 
     
    int a = (int)(Math.random()*(high-low+1)+low);  
    int b = (int)(Math.random()*(high-low+1)+low);  
    int c = (int)(Math.random()*(high-low+1)+low);   
    
    totnum = a + b + c;
    NumAvr = totnum / 3;
    
    System.out.println("The random grades are: "+a+", "+b+", "+c);
    System.out.println("====================================================");
    System.out.println("The highest number is: "+ Math.max(a, Math.max(b, c)));
    System.out.println("The second number is: "+ Math.max(b, c));
    System.out.println("The lowest number is: "+ Math.min(a, Math.min(b, c)));
    System.out.println("The average of three numbers is: "+dcf.format(NumAvr)+"%");
     

    //MathClass.java
  }
}



我面临的问题是我正在努力获得最高和最低的“中间”值。是否有任何“中间”变量让我在不使用任何条件语句或数组的情况下获得第二高?

totnuma + b + c。找到min,找到max。从 totnum 中减去第二高的值。此外,更喜欢在初始化变量时声明它们。 不要 执行整数数学运算来求平均值。您可以使用 printf 进行格式化。喜欢,

int high = 100;
int low = 75;
int a = (int) (Math.random() * (high - low + 1) + low);
int b = (int) (Math.random() * (high - low + 1) + low);
int c = (int) (Math.random() * (high - low + 1) + low);
int totnum = a + b + c;
System.out.printf("The random grades are: %d, %d, %d%n", a, b, c);
System.out.println("====================================================");
int highest = Math.max(a, Math.max(b, c));
int smallest = Math.min(a, Math.min(b, c));
int second = totnum - highest - smallest;
System.out.printf("The highest number is: %d%n", highest);
System.out.printf("The second number is: %d%n", second);
System.out.printf("The lowest number is: %d%n", smallest);
System.out.printf("The average of three numbers is: %.2f%%%n", totnum / 3.0);

示例输出

The random grades are: 87, 93, 89
====================================================
The highest number is: 93
The second number is: 89
The lowest number is: 87
The average of three numbers is: 89.67%

你可以这样做:

int max=Math.max(a, Math.max(b, c));
int min=Math.min(a, Math.min(b, c));
int inBetween=totnum - max -min:

这是一种无需任何算术即可完成的方法。

int maximum(int a, int b, int c) {
    return Math.max(a, Math.max(b, c));
}

/**
 *  There are two conditions on the middle number. 
 *  1) It must not be maximum. The three Math.min s ensure this.
 *  2) Of the numbers which are not maximum, it should be the maximum.
 */
int middle(int a, int b, int c) {
    int minAb = Math.min(a, b);
    int minBc = Math.min(b, c);
    int minAc = Math.min(a, c);
    return maximum(minAb, minBc, minAc);
}

如果你可以使用 streams 第二个你可以这样做:

int second = IntStream.of(a, b, c).sorted().skip(1).limit(1).findAny().getAsInt();

使用标准 Math.min / Math.max 函数的问题在于它们使用比较和三元运算符 under the hood:

public static int max(int a, int b) {
    return (a >= b) ? a : b;
}

因此,如果本练习的目的是完全避免广义上的条件运算,则可以通过计算最小值和最大值。

例如,在 C 中,以下公式 may be used 可检测最大数 max = (a > b) × b + (b > a) × a; 但它在 Java 中不起作用,因为比较运算符会导致 boolean值。

但是在计算两个数字之间的差异时,可以稍微修改此方法以检查负号,并将负号转换为 1(a < b),否则为 0(a >= b)使用位掩码和移位操作:

final int s = 0x80000000; // bit mask for sign
int min = (((a - b) & s) >>> 31) * a + (((b - a) & s) >>> 31) * b;
int max = (((a - b) & s) >>> 31) * b + (((b - a) & s) >>> 31) * a;

因此,对于三个随机输入值真正无条件按排序顺序打印它们的解决方案可能如下所示:

static void minMax(int a, int b, int c) {
    final int s = 0x80000000;
    System.out.print(a + ", " + b + ", " + c + " -> ");
    int min = (((a - b) & s) >>> 31) * a + (((b - a) & s) >>> 31) * b;
    int max = (((a - b) & s) >>> 31) * b + (((b - a) & s) >>> 31) * a;
    // or int max = a + b - min;
    
    min = (((min - c) & s) >>> 31) * min + (((c - min) & s) >>> 31) * c; 
    max = (((c - max) & s) >>> 31) * max + (((max - c) & s) >>> 31) * c;
    int mid = a - min + b - max + c;
    
    System.out.println(min + ", " + mid  + ", " + max);
    System.out.println("-----");
}

测试:

minMax(2, 3, 1);
minMax(2, 0, 6);
minMax(4, 2, -4);

输出:

2, 3, 1 -> 1, 2, 3
-----
2, 0, 6 -> 0, 2, 6
-----
4, 2, -4 -> -4, 2, 4
-----