2017-01-25 6 views
1

Я пытаюсь найти целую середину между двумя целыми числами. Например, середина (2,3) будет равна 2, а не 2,5. У меня было нижеследующее, которое отлично работает, но я хотел бы работать с числами от MIN_VALUE до MAX_VALUE, и это приводит к переполнению, так что абсолютно неверные результаты.Java, находящий среднюю точку между двумя целыми числами

public static int mid(int x, int y){ 
    int midpoint = (x+y)/2; 
    return midpoint; 
} 

Я теперь получил:

public static int mid(int x, int y){ 
    int low = Math.min(x, y); 
    int high = Math.max(x, y); 
    int midpoint = (low + high) >>> 1; 
    return midpoint; 
} 

Это похоже на работу для значений х и у от 0 до Integer.MAX_VALUE, однако неверно, если х является отрицательным числом, и я» m unsure, почему это?

+0

Он также не работает, если 'x + y> MAX_VALUE'. – molbdnilo

+1

Сделайте это с 'double', а затем конвертируйте обратно в int? Продвигайте 'int' '' '' '' '' '' '' ''' '' '' '' '' '' '' '' '' '' – markspace

+0

Невозможно воспроизвести неправильное поведение по отрицательному целому числу. Единственное, что я мог проверить, это то, что на этот код влияют проблемы с переполнением. – Paul

ответ

1

Вы можете работать вокруг с обращенным долго и обратно:

public static int mid(int x, int y) { 
    return (int) (((long)x + y)/2); 
} 
+0

Не может '(long) x + y' переполнять целое число? –

+0

нет, он будет выдавать длинные – Jerry06

+1

Если одно из значений в арифметической операции (+, -, *, /,%) длинное, тогда все значения преобразуются в длинный тип перед выполняемой арифметической операцией. Поэтому '(long) x + y' вернет' long', после этого '((long) x + y)/2' вернет' long', но все еще находится в 'int' диапазоне, поэтому приведение в' int' будет работать – Jerry06

1

А что-то вроде этого?

public static int mid(int x, int y){ 
    long difference = (long)y - x; 
    long adDiff = difference/2; 
    return (long) (x + adDiff); 
} 

Вы должны бросить его долго, так что в случае, когда y-x больше, то MAX_VALUE вы не переполнения.

0

оператор >>> заполняет верхние биты с нулем, в отличие от >> расширяющего знакового бита в верхний bits.so оператора побитового >> полезно:

public static int mid(int x, int y){ 
    int midpoint = (x>>1) + (y>>1); 

    if((x&0b1)/0b1==1&&(y&0b1)/0b1==1){ 
     midpoint++; 
    } 

    return midpoint; 
} 

, например: 1111 1110 (десятичное -2) + 0000 0001 (десятичное 1) = 1111 1111 (десятичное -1)

1111 1111 (десятичное -1) >> 1 = 1111 1111 (десятичное -1)

в то время как

1111 1111 (десятичное -1) >>> 1 = 0111 1111 (десятичное 127)

(тип Java 'Integer' 4 байта, здесь только для иллюстрации)

Я думаю, что это может быть полезно, чтобы понять результат;

+0

Хорошо, теперь я вижу разницу в этих операторах, но даже с помощью >>, похоже, переполнение. Середина Integer.MAX_VALUE и Integer.MAX_VALUE должна быть целым.MAX_VALUE, однако, равно -1, а для mid (MIN_VALUE, MIN_VALUE) отображается 0. – user7466895

+0

вы можете попробовать 'int midpoint = (x >> 1) + (y >> 1);', конечно, Integer.MAX_VALUE и Integer .MAX_VALUE - Integer.MAX_VALUE - 1 –

+0

Я hava отредактировал ответ. '(X & 0b1)/0b1' - это получить последний бит-код –

1

Как насчет этого?

public static int mid(int x, int y) { 
    return x/2 + y/2 + (x%2 + y%2)/2; 
} 
Смежные вопросы