Comments 27
& 0xff
-1
И еще, много где встречал использование char как uint16
+3
Для беззнакового short во многих ситуациях можно также использовать char.
+1
Почему не упоминаете Integer(Long).compare(divide)Unsigned() методы?
А как же Integer.rotateLeft(Right)?
Последние 4 осуществляют циклические сдвиги, их эквивалентов в Java нет.
А как же Integer.rotateLeft(Right)?
+2
Оп-па, а я и забыл про rotateLeft-Right. Спасибо. А про Integer(Long).compare(divide)Unsigned() не понял — в стандартной библиотеке вроде бы такого нет.
0
В Java 8, которая уже, на минуточку, скоро полгода как основная версия.
0
У кого-то она, может, и основная, но самая распространённая Java-платформа недавно только на Java7 (и то не полностью) переползла.
+4
Это здорово, что в 8 появились! А я смотрел в доках к семёрке, поэтому и не увидел. Но всё равно пока придётся уж иметь в виду ручные реализации деления и сравнения, поддержка семёрки всё-таки желательная вещь сейчас.
0
Посмотрите реализацию Long.divideUnsigned, он считает в BigInteger'ах если делитель отрицателен :(
+2
Что-то туплю, в чём смысл «Integer.compare( a ^ 0x80000000, b ^ 0x80000000 );»?
Ведь мы меняем знак (старший бит) у обоих операндов, нет?
Ведь мы меняем знак (старший бит) у обоих операндов, нет?
+1
Эта операция (инвертирование знака) проецирует пространство значений [0;2^32-1] на [-2^31;2^31-1] для обоих операндов. Далее производится обычное сравнение. Например, было число -1 (0xffffffff), оно станет 0x7fffffff. Было число 10 (0x0000000a), станет -10 (0x8000000a). 0x7fffffff > 0x8000000a.
0
На самом деле это такая небольшая обфускация: правильнее будет
Подобные же трюки часто приходится производить работая с SSE.
Ну а дальше можно заметить что
Integer.compare(a - 0x80000000, b - 0x80000000);
, где как бы понятно как всё работает. Мы переходим от чисел в интервале от 0
до 0xffffffff
к часлам в интервале от 0x80000000
до 0x7ffffff
путём линейного сдвига (мы стартуем с чисел без знака, а результатом является число без знака, но «так можно», потому что в арифметике «с дополнением до двух» сложение и вычитанием одинаково и для чисел без знака и для чисел со знаком) — а после этого уже все сравнения нормально можно производить.Подобные же трюки часто приходится производить работая с SSE.
Ну а дальше можно заметить что
0x80000000
— это такое особенное число, что его что вычесть, что прибавить, что про XOR'ить — всё равно. Не знаю, правда, какой смысл в этой обфускации.+5
Не знаю, правда, какой смысл в этой обфускации.
Побитовые операции быстрее (хотя на дворе 2014 год, и может уже и не быстрее).
0
Собственно, в 8 джаве так и сделано
public static int compareUnsigned(int x, int y) {
return compare(x + MIN_VALUE, y + MIN_VALUE);
}
+2
И зачем так сложно long делить.
Что плохо в этом:
Одна строчка — всё инлайнится и оптимизируется.
Что плохо в этом:
public static long ulongDiv(final long a, final long b) {
return b>1L || b<0 ? (a>>>1)/(b>>>1) : a/b;
}
Одна строчка — всё инлайнится и оптимизируется.
-3
А теперь представьте, что через 3 года натыкаетесь на этот кусок кода. Сколько вам понадобиться времени, чтобы понять как это работает?
+2
Если я его за пять секунд придумал, то очевидно, что пять секунд. А во-вторых, вся подобная магия должна быть документирована. Тут даже по имени функции видно, что она делает.
Это не более запутано чем Integer.compare( a ^ 0x80000000, b ^ 0x80000000 ) и уж точно гораздо более понятно, чем тот, кусок кода из пяти функций, который в статье приведен. Вы внимательно посмотрели, что именно в статье предлагается использовать? Четыре процедуры, два из которых весьма не очевидны. А уж оптимизация сравнивать…
Это не более запутано чем Integer.compare( a ^ 0x80000000, b ^ 0x80000000 ) и уж точно гораздо более понятно, чем тот, кусок кода из пяти функций, который в статье приведен. Вы внимательно посмотрели, что именно в статье предлагается использовать? Четыре процедуры, два из которых весьма не очевидны. А уж оптимизация сравнивать…
+2
ulongDiv(10, 3) возвращает 5
+9
Собственно, даже проще:
public static long ulongDiv(final long a, final long b) {
return b!=1L? (a>>>1)/(b>>>1): a/b;
}
В отличи от гугеля, понятно, инлайнится и скорее всего для констант будет просто статически вычислено. Причём, если b — константа, то тоже будет отлично заоптимизированно.
public static long ulongDiv(final long a, final long b) {
return b!=1L? (a>>>1)/(b>>>1): a/b;
}
В отличи от гугеля, понятно, инлайнится и скорее всего для констант будет просто статически вычислено. Причём, если b — константа, то тоже будет отлично заоптимизированно.
-3
Да вы прямо математик, да. Делим 9 на 3 и получаем… 4. Это ж просто праздник какой-то!
P.S. Только не надо приводить ещё один «ещё более очевидный» вариант. В конце-концов доберётесь-таки до чего-то подобного Гугловому варианту. С 10й попытки. Я в вас верю. Но вопрос «почему всем идиотам всё далеко не так очевидно, как мне» вроде как уже отпал. Или нет?
P.S. Только не надо приводить ещё один «ещё более очевидный» вариант. В конце-концов доберётесь-таки до чего-то подобного Гугловому варианту. С 10й попытки. Я в вас верю. Но вопрос «почему всем идиотам всё далеко не так очевидно, как мне» вроде как уже отпал. Или нет?
+23
Я бы еще добавил самой первой рекомендацией: Никогда не используйте нигде, кроме тщательно локализованных модулей взаимодействия с legacy данными и низкоуровневыми протоколами.
В библиотеке javolution есть класс Struct для работы с такого типа данными.
В библиотеке javolution есть класс Struct для работы с такого типа данными.
+1
Для каких-то исключительных случаев такой метод, возможно, и будет полезным, но я в java скорее предпочту использовать знаковые типы достаточной для хранения данных разрядности, нежели городить подобные обёртки. Просто потому, что в процессе разработки все эти пляски забудутся, и начнутся чудеса при сравнении знаковых с беззнаковыми, «неправильными» операциями и т.д.
+4
Sign up to leave a comment.
Беззнаковая арифметика в Java