如何检查一个整数是否在给定的范围内?

113

希望得到更优雅的解决方案

if (i>0 && i<100) 

9
你手上的东西有什么问题吗? - GreenMatt
3
明显的解决方案是创建一个 class RangeChecker<Integer>,我相信你可以从那里填写详细信息。 - corsiKa
7
或许OP希望在语义上类似于SELECT * FROM aTable WHERE aDate BETWEEN lower AND upper中的BETWEEN,以便进行翻译。 - Simen S
17
有趣的是,Python 允许像这样使用语法 0 < i < 100 进行测试。 - Greg Hewgill
3
Apache Commons类org.apache.commons.lang.math.IntRange可能适合您。 - Abhishek
显示剩余5条评论
22个回答

259

你可以添加间距 ;)

if (i > 0 && i < 100) 

13
不要限制我的风格!不,我通常会这样分隔开。 - herpderp
22
有一个建议是,由于我们通常会写类似于“0 < i < 100”的内容,因此尽可能遵循这一规则可以使代码更易于阅读:0 < i && i < 100。在 0 < i 中将常量放在左侧有点奇怪,但我认为为了整个表达式看起来最像 0 < ... < 100,这样做是值得的。 - Joshua Taylor
N > 2 && N < 5,表示N的值介于2和5之间。 - undefined

63

3
这很低效。 - Wouterr

38
我认为
if (0 < i && i < 100) 

更加优雅。看起来像数学方程。

如果您正在寻找特别的东西,可以尝试:

Math.max(0, i) == Math.min(i, 100)

至少它使用了库。


13
注意第二个解决方案是包容的,第一个不是。 - holmis83
难道不应该是Math.min(i, 99)吗?因为如果我输入100它仍然会返回true。我认为当0 < i <= 100时,Math.max(0, i) == Math.min(i, 100)可行。 - Irshu
@Irshu 不完全正确 - 因为如果 i = 0,那么 Math.max(0, i) == Math.min(i, 99) 仍然会计算为 0 == 0 - domids

20
ValueRange range = java.time.temporal.ValueRange.of(minValue, maxValue);
range.isValidIntValue(x);
  • 如果 minValue <= x <= maxValue,即在范围内,则返回true
  • 如果x < minValue 或者 x > maxValue,即超出范围,则返回false

使用方法如下所示:

int value = 10;
if (ValueRange.of(0, 100).isValidIntValue(value)) {
    System.out.println("Value is with in the Range.");
} else {
    System.out.println("Value is out of the Range.");
}

下面的程序检查hasTeen方法中传递的任何整数值是否在13(包括13)到19(包括19)范围内。


import java.time.temporal.ValueRange;
  
public class TeenNumberChecker {

    public static void main(String[] args) {
        System.out.println(hasTeen(9, 99, 19));
        System.out.println(hasTeen(23, 15, 42));
        System.out.println(hasTeen(22, 23, 34));
    }

    public static boolean hasTeen(int firstNumber, int secondNumber, int thirdNumber) {

        ValueRange range = ValueRange.of(13, 19);
        System.out.println("*********Int validation Start ***********");
        System.out.println(range.isIntValue());
        System.out.println(range.isValidIntValue(firstNumber));
        System.out.println(range.isValidIntValue(secondNumber));
        System.out.println(range.isValidIntValue(thirdNumber));
        System.out.println(range.isValidValue(thirdNumber));
        System.out.println("**********Int validation End**************");

        if (range.isValidIntValue(firstNumber) || range.isValidIntValue(secondNumber) || range.isValidIntValue(thirdNumber)) {
            return true;
        } else
            return false;
    }
}

输出

true 因为19在范围内

true 因为15在范围内

false 因为所有三个值都超出了范围


很好,我已经在if条件语句中使用它,例如 - if(ValueRange.of(90, 100).isValidIntValue(91)) { "值在范围内。" } - Yash
注意: 实际上,ValueRange类并不是直接用于纯整数比较,而是用于(引用来自JavaDocs,重点在于):"日期时间字段的有效值范围"。 - informatik01

13

我认为这是一种优雅的比较范围的方法。但是,这种方法会导致您编写额外的单元测试来满足所有&&情况。

因此,您可以使用以下任何一种方法来避免编写额外的单元测试。

使用Java 8 Streams:

if(IntStream.rangeClosed(0,100).boxed().collect(Collectors.toList()).contains(i))

使用 Math 类:

if(Math.max(0, i) == Math.min(i, 100))

个人建议采用第二种方法,因为它不会创建与要检查的范围大小相等的数组。


无论如何,您必须编写所有单元测试。不同之处在于,它可能不会被代码检查工具记录。 - kap
@kap 显然,应该编写所有有效的单元测试。但是,OP使用的方法将需要一个几乎不可能覆盖的测试用例,即false && false。这就是为什么我提到了一种避免覆盖此无效额外测试用例的方法。 - Sahil Chhabra
Streams解决方案非常糟糕。考虑一个更大的范围,从-2.000.000.000到2.000.000.000。创建一个四十亿条目的列表,仅仅为了检查其中一个值是否存在,这简直是疯狂的行为。 - Sven Döring
@SvenDöring 显然它不适用于更大的范围,我已经在我的答案最后一行提到了。另外,请注意,这个答案是针对问题中提到的范围,即0-100。 - Sahil Chhabra

8

我认为这很优雅,但如果您经常重复使用表达式,则将其放入方法中是一个好主意,例如:

class MathUtil
{
   public static boolean betweenExclusive(int x, int min, int max)
   {
       return x>min && x<max;    
   }
}

如果你混合使用包含和不包含的比较,这一点尤其重要。方法名称可以帮助避免拼写错误,例如使用 < 时应该使用 <=。该方法还可以确保 min < max 等。


9
直到有人把布尔变量accepted=MathUtil.betweenExclusive(min,max,x)搞错顺序,否则这是一个好主意。 :( - corsiKa
我知道!哎呀。在这种情况下,一个范围对象可能会很有用。 - mdma
我的RangeChecker对象实际上是一个玩笑,但事后看来,它其实并不是一个那么糟糕的解决方案(即使有些过度设计了)。 - corsiKa
如果它是在Integer类中直接定义的方法会更好。当你使用myNum.isBetween(min, max)时,不会有任何混淆。 - buræquete
简单示例:我有一个人员名单,其中包含他们的年龄,并想检查每个人是老年人、中年人、儿童还是幼儿。我可以拥有命名范围的年龄,然后我的代码就非常易读。或者我可以有很多>和<,那么我的代码就会变得混乱不堪。 - Mikhail Batcer

6

如果您正在寻找比较原创的东西,而不是

if (i > 0 && i < 100)

你可以尝试这个

import static java.lang.Integer.compare;
...
if(compare(i, 0) > compare(i, 100))

4

这个人写了一个不错的范围类。

然而,由于它是一个通用类,使用它并不能产生良好的代码。你需要输入类似以下的内容:

if (new Range<Integer>(0, 100).contains(i))

或者(如果您先实现的话会更好):
class IntRange extends Range<Integer>
....
if (new IntRange(0,100).contains(i))

在语义上,它们都比Java默认提供的更好,但是内存开销、性能降低和整体打字量都不值得。个人而言,我更喜欢 mdma的方法

1
范围类URL的页面未找到。 - Shridutt Kothari

4

谷歌的Java库Guava也实现了范围(Range)

import com.google.common.collect.Range;

Range<Integer> open = Range.open(1, 5);
System.out.println(open.contains(1)); // false
System.out.println(open.contains(3)); // true
System.out.println(open.contains(5)); // false

Range<Integer> closed = Range.closed(1, 5);
System.out.println(closed.contains(1)); // true
System.out.println(closed.contains(3)); // true
System.out.println(closed.contains(5)); // true

Range<Integer> openClosed = Range.openClosed(1, 5);
System.out.println(openClosed.contains(1)); // false
System.out.println(openClosed.contains(3)); // true
System.out.println(openClosed.contains(5)); // true

3
if ( 0 < i && i < 100)  

if ( 'a' <= c && c <= 'z' )

1
除了第一个例子中不一致的间距外,完美无缺! - Jakub Hampl
1
很遗憾,6个字符的规则阻止了对间距进行任何修复。 - Martin
1
更好的字符检查是 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) - Octavia Togami
1
甚至更好:Character.isLetter(c) - Roland Illig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接