假设一个整数应该在范围[0...2147483647]
内。
我想检查一个整数变量是否在这个范围内。我知道可以通过简单的if-else语句来实现,但是否有更有效的方法来检查它是否在这个范围内?
我不想这样做:
if (foo >= 0 && foo <= 2147483647)
{
// do something
}
假设一个整数应该在范围[0...2147483647]
内。
我想检查一个整数变量是否在这个范围内。我知道可以通过简单的if-else语句来实现,但是否有更有效的方法来检查它是否在这个范围内?
我不想这样做:
if (foo >= 0 && foo <= 2147483647)
{
// do something
}
Apache Commons Lang有一个用于处理任意范围的Range
类。
Range<Integer> test = Range.between(1, 3);
System.out.println(test.contains(2));
System.out.println(test.contains(4));
Guava 的Range
具有类似的 API。
如果您只想检查一个数字是否适合长整型或整型值,可以尝试使用 BigDecimal
。它提供了longValueExact
和 intValueExact
方法,如果值超出这些精度范围会抛出异常。
.contains(...)
是如何实现的呢? ;) (肯定是用 if/else :)) - PhDRange
的问题在于它似乎缺少类似于 addWrap()
和 subtractWrap()
的概念,当你需要将一个值向下减去到最小值以下时,以包装到最大值,或者类似地对一个值进行增加/添加,以包装到最大值时,这两个概念都非常有用。如果需要,甚至可以使用 %
并允许浮点数。这些很容易自己实现,但是我认为它们至少应该是 Math
方法,以利用可能存在的任何本地级别的原子操作。 - alife你可以创建一个类来表示这个
public class Range
{
private int low;
private int high;
public Range(int low, int high){
this.low = low;
this.high = high;
}
public boolean contains(int number){
return (number >= low && number <= high);
}
}
用例示例:
Range range = new Range(0, 2147483647);
if (range.contains(foo)) {
//do something
}
low <= high
)。区间必须是半开放的 [low, high)
或者使用 extent
代替 high
。 - Richard我知道这是一个很老的问题,但是使用Java 8的Streams,您可以像这样获取一系列int
:
// gives an IntStream of integers from 0 through Integer.MAX_VALUE
IntStream.rangeClosed(0, Integer.MAX_VALUE);
然后你可以这样做:
if (IntStream.rangeClosed(0, Integer.MAX_VALUE).matchAny(n -> n == A)) {
// do something
} else {
// do something else
}
A
。另一方面,你只需要进行一次实际比较,即A >= 0
。 - Holger您可以使用 java.time.temporal.ValueRange
,它接受 long
并且也可以与 int
一起使用:
int a = 2147;
//Use java 8 java.time.temporal.ValueRange. The range defined
//is inclusive of both min and max
ValueRange range = ValueRange.of(0, 2147483647);
if(range.isValidValue(a)) {
System.out.println("in range");
}else {
System.out.println("not in range");
}
无论你如何努力优化这个不太密集的计算,你都会有一个if-check :) 你可以从数字中减去上限,如果结果为正数,那么你就知道超出了范围。你可以使用一些布尔位移逻辑来解决问题,甚至可以使用费马定理(开玩笑:)。但是,关键是“为什么”需要优化此比较?目的是什么?
Comparable
,我使用以下代码:
public class Range<T extends Comparable<T>> {
/**
* Include start, end in {@link Range}
*/
public enum Inclusive {START,END,BOTH,NONE }
/**
* {@link Range} start and end values
*/
private T start, end;
private Inclusive inclusive;
/**
* Create a range with {@link Inclusive#START}
* @param start
*<br/> Not null safe
* @param end
*<br/> Not null safe
*/
public Range(T start, T end) { this(start, end, null); }
/**
* @param start
*<br/> Not null safe
* @param end
*<br/> Not null safe
*@param inclusive
*<br/>If null {@link Inclusive#START} used
*/
public Range(T start, T end, Inclusive inclusive) {
if((start == null) || (end == null)) {
throw new NullPointerException("Invalid null start / end value");
}
setInclusive(inclusive);
if( isBigger(start, end) ) {
this.start = end; this.end = start;
}else {
this.start = start; this.end = end;
}
}
/**
* Convenience method
*/
public boolean isBigger(T t1, T t2) { return t1.compareTo(t2) > 0; }
/**
* Convenience method
*/
public boolean isSmaller(T t1, T t2) { return t1.compareTo(t2) < 0; }
/**
* Check if this {@link Range} contains t
*@param t
*<br/>Not null safe
*@return
*false for any value of t, if this.start equals this.end
*/
public boolean contains(T t) { return contains(t, inclusive); }
/**
* Check if this {@link Range} contains t
*@param t
*<br/>Not null safe
*@param inclusive
*<br/>If null {@link Range#inclusive} used
*@return
*false for any value of t, if this.start equals this.end
*/
public boolean contains(T t, Inclusive inclusive) {
if(t == null) {
throw new NullPointerException("Invalid null value");
}
inclusive = (inclusive == null) ? this.inclusive : inclusive;
switch (inclusive) {
case NONE:
return ( isBigger(t, start) && isSmaller(t, end) );
case BOTH:
return ( ! isBigger(start, t) && ! isBigger(t, end) ) ;
case START: default:
return ( ! isBigger(start, t) && isBigger(end, t) ) ;
case END:
return ( isBigger(t, start) && ! isBigger(t, end) ) ;
}
}
/**
* Check if this {@link Range} contains other range
* @return
* false for any value of range, if this.start equals this.end
*/
public boolean contains(Range<T> range) {
return contains(range.start) && contains(range.end);
}
/**
* Check if this {@link Range} intersects with other range
* @return
* false for any value of range, if this.start equals this.end
*/
public boolean intersects(Range<T> range) {
return contains(range.start) || contains(range.end);
}
/**
* Get {@link #start}
*/
public T getStart() { return start; }
/**
* Set {@link #start}
* <br/>Not null safe
* <br/>If start > end they are switched
*/
public Range<T> setStart(T start) {
if(start.compareTo(end)>0) {
this.start = end;
this.end = start;
}else {
this.start = start;
}
return this;
}
/**
* Get {@link #end}
*/
public T getEnd() { return end; }
/**
* Set {@link #end}
* <br/>Not null safe
* <br/>If start > end they are switched
*/
public Range<T> setEnd(T end) {
if(start.compareTo(end)>0) {
this.end = start;
this.start = end;
}else {
this.end = end;
}
return this;
}
/**
* Get {@link #inclusive}
*/
public Inclusive getInclusive() { return inclusive; }
/**
* Set {@link #inclusive}
* @param inclusive
*<br/>If null {@link Inclusive#START} used
*/
public Range<T> setInclusive(Inclusive inclusive) {
this.inclusive = (inclusive == null) ? Inclusive.START : inclusive;
return this;
}
}
(这是一个较为简短的版本。完整代码可在此处找到。)
import java.util.Arrays;
class Soft{
public static void main(String[] args){
int[] nums=range(9, 12);
System.out.println(Arrays.toString(nums));
}
static int[] range(int low, int high){
int[] a=new int[high-low];
for(int i=0,j=low;i<high-low;i++,j++){
a[i]=j;
}
return a;
}
}
我的代码类似于 Python 的 range :)
if
语句会获胜。不过,我同意这个观察结果不应该主导你的决策。对于99%的应用程序来说,维护效率才是更重要的。 - Ole V.V.if(foo >= 0) …
,因为根本没有必要检查一个int
是否<=Integer.MAX_VALUE
。但我怀疑提问者会不会阅读这些评论,因为缺席五年后回来的可能性很小。 - Holger