Странность сдвига разряда Java

Java имеет 2 оператора сдвига разряда для сдвигов вправо:

>> shifts right, and is dependant on the sign bit for the sign of the result

>>> shifts right and shifts a zero into leftmost bits

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html

Это кажется довольно простым, так может любой объяснять мне, почему этот код при предоставлении значения-128 для панели производит значение-2 для нечто:

byte foo = (byte)((bar & ((byte)-64)) >>> 6);

То, что это предназначено, чтобы сделать, является взятием байт на 8 битов, маска крайних левых 2 битов, и сместите их в самые правые 2 бита. Т.е.:

initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b10000000
0b10000000 >>> 6 = 0b00000010

Результат на самом деле-2, который является

0b11111110

Т.е. 1 с, а не нули смещается в оставленные должности

5
задан Jon Seigel 3 May 2010 в 02:54
поделиться

3 ответа

ItiveControl является вашим другом:

<ItemsControl ItemsSource="{Binding YourChildItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
-121--1713818-

Когда вы говорите C нравится, он идет в том же направлении, что и другие. Scala каким-то образом устраняет нули с помощью вариантов. Тем не менее, можно использовать нулевые значения. Функциональные языки не имеют нулевых проблем и побочных эффектов, но они не c как. Динамические языки также имеют значения null или неопределенные переменные и т. д. Это цена, которую вы должны заплатить за c, как imho.

-121--4460266-

Это потому, что & на самом деле выполняет продвижение до int - что оставляет ужасно много «1» битов. Затем вы смещаетесь вправо, оставляя самые левые 2 бита как 0, но затем игнорируете эти самые левые биты, возвращая их в байт.

Это становится более ясным, когда вы отделяете операции:

public class Test
{
    public static void main(String[] args)
    {
        byte bar = -128;
        int tmp = (bar & ((byte)-64)) >>> 6;
        byte foo = (byte)tmp;
        System.out.println(tmp);
        System.out.println(foo);
    }
}

печатает

67108862
-2

Так что сделать свой бит арифметика снова:

initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b11111111111111111111111110000000 // it's an int now
0b10000000 >>> 6 = 0b00111111111111111111111111100000 // note zero-padding
(byte) (0b10000000 >>> 6) = 11100000 // -2

Даже если вы получите правильный результат из операции & (путем кастинга в тот пункт), > > > будет продвигать первый операнд до int в первую очередь.

EDIT: Решение состоит в том, чтобы изменить способ маскировки вещей. Вместо маскирования на -64 маска просто на 128 + 64 = 192 = 0xc0 вместо этого:

byte foo = (byte)((bar & 0xc0) >>> 6);

Это путь вы действительно получить только с двумя битами вы хотите, вместо того, чтобы иметь нагрузку 1 s в наиболее старших битов 24.

8
ответ дан 13 December 2019 в 05:35
поделиться

afaik, в Java большинство операторов (+, -, >> и т. Д.) Не может работать над тем, что меньше, чем int s. Таким образом, ваши побитовые сдвиги и и неявно отличаются значения в int на заднем плане, а затем обратно в байт вашим явным выбросом снаружи. Последний акт избавляется от нулей в более высоких битах.

Чтобы получить результаты, которые вы ожидаете, попробуйте делать это на int S.

2
ответ дан 13 December 2019 в 05:35
поделиться

Другие говорили вам, почему, но я все сломут его и предоставим ответ на реальную проблему.

byte foo = (byte)((bar & ((byte)-64)) >>> 6);

Поскольку и оператор будет продвигать все, что это означает, что это делает, по сути:

byte foo = (byte)(((int)bar & (int)((byte)-64)) >>> 6);

, если стержень IS -128, затем (INT) BAR - это 0xFFFFFFFF80, который является затем и «с 0xFFFFFFF0, Затем вы сместите это правильное 6 мест, чтобы получить: 0x3ffffffe

Правильный ответ действительно прост:

byte foo = (byte)((bar & 0xC0) >> 6);

Бар продвигается в int для операции и операции, поэтому единственное, что осталось в том, что int int будет два верхних бита Оригинальный байт. Затем переместите его вправо 6 битов и преобразуйте его обратно в байты.

2
ответ дан 13 December 2019 в 05:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: