Беззнаковый короткий в Java

Как я могу объявить значение unsigned short в Java?


person maiky    schedule 03.12.2009    source источник
comment
Связанный вопрос, если вас интересует мотивация этого: почему Java не поддерживает беззнаковые целые числа? stackoverflow.com/questions/430346   -  person Heinzi    schedule 03.12.2009
comment
@ PP: Если вам нужен язык с сильными сторонами Java и C ++, я могу порекомендовать Scala. Это действительно хорошо, когда ты позволяешь себе безумствовать с типами.   -  person Carl Smotricz    schedule 03.12.2009
comment
используйте короткую подпись. все соответствующие битовые операции имеют вариации, при которых значение трактуется как беззнаковое.   -  person james    schedule 03.12.2009
comment
@Peter, по большей части знаковая математика подходит. Но когда вы хотите начать манипулировать битами, беззнаковый всегда был самым безопасным способом из-за различных реализаций знаковой математики. Это все равно, что не брать с собой инструменты, чтобы сменить шину в машине. Для большинства людей это нормально почти всегда. Но когда придет время, вы очень этого захотите!   -  person PP.    schedule 04.12.2009
comment
@Heinzi, если вы кодируете контроллер OpenFlow, сетевые устройства отправляют сообщения в виде целочисленных значений без знака, и, таким образом, эти случаи изящно обрабатываются в контроллерах на основе C / C ++, в то время как, например, Beacon Controller (на основе Java), уйти от этого, вручную выполняя бит операции над ним, чтобы вернуть беззнаковое значение, что явно является проблемой ***. Я думаю, им следует ввести беззнаковые типы данных в Java 8   -  person Space Rocker    schedule 05.10.2012
comment
@PP Битовые операции четко определены для значений со знаком в Java.   -  person starblue    schedule 28.12.2012
comment
Я наткнулся на этот вопрос, потому что мне нужен был беззнаковый короткий для операций с портами: максимально возможный порт - 65535, что «случайно» является максимально возможным значением в 2 байта, то есть коротким.   -  person ethguo    schedule 21.04.2013


Ответы (16)


Вы действительно не можете. В Java нет беззнаковых типов данных, кроме char.

По общему признанию, вы могли бы использовать char - это 16-битный беззнаковый тип - но это было бы ужасно, на мой взгляд, поскольку char явно предназначен для текста: когда код использует char, я ожидаю, что это будет используя его для кодовых единиц UTF-16, представляющих интересный для программы текст, а не произвольные беззнаковые 16-битные целые числа, не имеющие отношения к тексту.

person Jon Skeet    schedule 03.12.2009
comment
@Jon: Кажется, в Java нет способа иметь нормальный байт машинного уровня, то есть 8-битное местоположение, которое может содержать значения [0–255] вместо [–128 - +127]. Я не могу поверить, что они заставляют нас использовать подписанные байты, когда все, что вам нужно сделать в C, это сказать unsigned char. Как только вы начнете использовать только подписанные типы данных, он испортит все ваши неподписанные растровые изображения. На самом деле довольно неприятно. Разработчики Java думали, что они упрощают вещи, чтобы сделать их менее подверженными ошибкам, но снова все, что им удалось сделать, - это сделать их намного сложнее и подверженными ошибкам, чем раньше. В Java этого много. - person tchrist; 24.08.2011
comment
@Jon: OTOH, поскольку Java char непригоден для кодовых точек Unicode, вы можете использовать его и для коротких замыканий без знака: он не будет ужаснее любого существующего кода, использующего char, когда им действительно следует использовать int. - person ninjalj; 24.08.2011
comment
@ninjalj, Ой где ты typedef? - person Pacerier; 20.08.2014
comment
@tchrist - ну, FWIW, на самом деле не совсем правильно подразумевать, что байт уровня машины равен 0-255, а не -128- + 127. Машинные байты - это всего лишь 8 бит, и интерпретация значения может зависеть от используемой инструкции. Во многих случаях, рассматриваете ли вы байт как знаковый или беззнаковый, на самом деле не имеет значения для сборки (например, сложение, вычитание, некоторое умножение, все битовые операции). Знаковая интерпретация не имеет значения для большинства битовых карт - все побитовые операторы работают должным образом. Вам нужно остерегаться только расширения подписи при конверсии. - person BeeOnRope; 04.11.2016
comment
Что именно делает char ужасным? Это скорее FUD, чем помощь. - person Aleksandr Dubinsky; 05.09.2017
comment
@AleksandrDubinsky: Нет ничего плохого в char как типе, но использование его как 16-битного целого числа без знака, а не текста - это злоупотребление типом, IMO. Когда я вижу char в коде, я думаю, что это кодовая единица UTF-16, а не произвольное 16-битное целое число. - person Jon Skeet; 05.09.2017
comment
@JonSkeet Было бы лучше привести конкретные причины, помимо стиля, прежде чем бросать такие слова, как ужас. Для будущих посетителей будет полезно повторить содержимое этого ответа stackoverflow.com/questions/397867/, чтобы объяснить, как использовать беззнаковые типы данных в Java. В Java 8 класс Integer представил некоторые из этих методов как методы toUnsignedLong, compareUnsigned, divideUnsigned и т. Д., Однако есть значение в полной документации, особенно потому, что класс Short не предоставлял эти методы. - person Aleksandr Dubinsky; 05.09.2017
comment
@AleksandrDubinsky: Я добавил свои рассуждения к ответу, но оставил там ужасные вещи, поскольку я считаю, что это это ужасно. Я не собираюсь повторять содержание других ответов в ответе почти восьмилетней давности. - person Jon Skeet; 05.09.2017
comment
@JonSkeet Эта страница и этот ответ набирают много просмотров. Конечно, вы не обязаны помогать сообществу. - person Aleksandr Dubinsky; 05.09.2017
comment
@AleksandrDubinsky: Как ты пассивно-агрессивен. Я думаю, мы здесь закончили. Если кто-то захочет перейти по вашей ссылке, он сможет увидеть там содержание другого ответа. - person Jon Skeet; 05.09.2017
comment
@AleksandrDubinsky: Помечено. Я здесь закончил. Мысль о том, что я работаю только на очки, оскорбительна и явно не соответствует действительности. - person Jon Skeet; 05.09.2017

Если вам действительно нужно значение ровно с 16 битами:

Решение 1. Используйте имеющееся краткое обозначение со знаком и не беспокойтесь о знаке, если вам не нужно выполнять операции сравнения (‹,‹ =,>,> =) или деления (/,%, >>). . См. этот ответ, чтобы узнать, как обрабатывать подписанные числа как если они были без подписи.

Решение 2 (где решение 1 не применяется): используйте младшие 16 бит int и удалите старшие биты с помощью & 0xffff, где это необходимо.

person starblue    schedule 03.12.2009
comment
sBuff.append( new Integer(iArray[i++] & 0xffff) + ","); спасибо! - person essa; 09.05.2016

Это действительно устаревшая тема, но она будет полезна всем, кто придет после. Символ - это числовой тип. Он поддерживает все математические операторы, битовые операции и т. Д. Это беззнаковое 16.

Мы обрабатываем сигналы, записанные специальным встроенным оборудованием, поэтому мы обрабатываем множество беззнаковых 16 из A-D. Мы много лет использовали символы повсюду, и у нас никогда не было никаких проблем.

person joel garringer    schedule 17.05.2012

Вы можете использовать char, поскольку это беззнаковое 16-битное значение (хотя технически это символ Unicode, поэтому в будущем он может потенциально измениться на 24-битное значение) ... другой альтернативой является использование int и убедитесь, что это в пределах досягаемости.

Не используйте char - используйте int :-)

А вот ссылка, в которой обсуждается Java и отсутствие неподписанных символов.

person TofuBeer    schedule 03.12.2009
comment
char определяется как 16-битный, а не символ Unicode (что бы это ни значило), всегда и навсегда. Если char изменится на 24 бита, это уже не будет Java. - person Ken; 03.12.2009
comment
Я тоже не думаю, что это когда-нибудь изменится. Причина, по которой 16 битов - это поддержка Unicode (из JLS: платформа Java отслеживает спецификацию Unicode по мере ее развития. Стандарт Unicode изначально был разработан как 16-битная кодировка символов фиксированной ширины) и из java.lang.Character : Методы, которые принимают только значение char, не могут поддерживать дополнительные символы - поэтому изначально char был 16-битным, потому что это было то, насколько широким был Unicode. Теперь Unicode больше, и char больше не может представлять все символы Unicode. - person TofuBeer; 03.12.2009

Из DataInputStream.java

public final int readUnsignedShort() throws IOException {
    int ch1 = in.read();
    int ch2 = in.read();
    if ((ch1 | ch2) < 0)
        throw new EOFException();
    return (ch1 << 8) + (ch2 << 0);
}
person mobiusinversion    schedule 20.10.2014

В Java такого типа нет

person paweloque    schedule 03.12.2009

Да нет такого, если вы хотите использовать значение в кодовых и битовых операциях.

person Jé Queue    schedule 03.12.2009


Нет, действительно такого метода нет, java - это язык высокого уровня. Вот почему в Java нет беззнаковых типов данных.

person muhammad Ahmad    schedule 08.08.2018

Он сказал, что хочет создать многомерный короткий массив. Еще никто не предлагал побитовые операторы? Из того, что я читал, вы хотите использовать 16-битные целые числа вместо 32-битных целых чисел для экономии памяти?

Итак, сначала для начала 10 000 x 10 000 коротких значений - это 1 600 000 000 бит, 200 000 000 байтов, 200 000 килобайт, 200 мегабайт.

Если вам нужно что-то с потребляемой памятью 200 МБ, вы можете переделать эту идею. Я также не верю, что даже скомпилировать, не говоря уже о запуске. Никогда не следует инициализировать такие большие массивы, если что-то использует 2 функции, называемые загрузкой по запросу и кэшированием данных. По сути, загрузка по запросу относится к идее загружать данные только по мере необходимости. Затем кэширование данных делает то же самое, но использует настраиваемый фрейм для удаления старой памяти и добавления новой информации по мере необходимости. У этого непросто получить ХОРОШИЕ скоростные характеристики. Есть и другие вещи, которые вы можете делать, но эти два являются моими любимыми, когда все сделано правильно.

Вернемся к тому, что я говорил о побитовых операторах.

Итак, 32-битное целое число или в Java "int". Вы можете хранить в нем то, что называется «битами», поэтому предположим, что у вас есть 32 логических значения, которые в Java все значения занимают 32 бита (кроме long), или для массивов они занимают 8 для байтов, 16 для краткости и 32 для int. . Поэтому, если у вас нет массивов, вы не получите никаких преимуществ памяти от использования байта или короткого замыкания. Это не означает, что вы не должны использовать его как способ убедиться, что вы и другие знаете диапазон данных, который должно иметь это значение.

Как я уже говорил, вы можете эффективно сохранить 32 логических значения в одно целое, выполнив следующие действия:

int many_booleans = -1; //All are true;
int many_booleans = 0; //All are false;
int many_booleans = 1 | 2 | 8; //Bits 1, 2, and 4 are true the rest are false;

Итак, теперь короткий состоит из 16 бит, поэтому 16 + 16 = 32, что ИДЕАЛЬНО подходит для 32-битного целого числа. Таким образом, каждое значение int может состоять из двух коротких значений.

int two_shorts = value | (value2 << 16);

Таким образом, приведенное выше значение находится в диапазоне от -32768 до 32767 или в виде беззнакового значения от 0 до 65535. Допустим, значение равно -1, так что в качестве значения без знака оно было 65535. Это будет означать, что биты с 1 по 16 включены. , но при фактическом выполнении математических расчетов учитывайте диапазон от 0 до 15.

Итак, нам нужно затем активировать биты 17–32. Итак, мы должны начать с чего-то большего, чем 15 бит. Итак, мы начинаем с 16 бит. Итак, взяв значение2 и умножив его на 65536, это то, что делает «‹---------------- 16». Теперь предположим, что value2 равняется 3, это будет OR 3x65536 = 196608. Таким образом, наше целочисленное значение будет равно 262143.

int assumed_value = 262143;

Итак, допустим, мы хотим получить два 16-битных целочисленных значения.

short value1 = (short)(assumed_value & 0xFFFF); //-1
short value2 = (short)(assumed_value >> 16); //=3

Также в основном думайте о побитовых операторах как о степени двойки. Вот и все, что они есть на самом деле. Никогда не смотрите на это с точки зрения нулей и единиц. Я в основном размещал это, чтобы помочь любому, кто может столкнуться с этим поиском беззнаковых коротких или даже, возможно, многомерных массивов. Если есть какие-то опечатки, прошу прощения, быстро написал это.

person Jeremy Trifilo    schedule 03.02.2014

Если возможно использование сторонней библиотеки, существует jOOU (дополнительная библиотека от jOOQ), который предлагает типы оболочки для целых чисел без знака в Java. Это не совсем то же самое, что поддержка примитивного типа (и, следовательно, байтового кода) для беззнаковых типов, но, возможно, этого достаточно для вашего варианта использования.

import static org.joou.Unsigned.*;

// and then...
UShort s = ushort(1);

(Отказ от ответственности: я работаю в компании, стоящей за этими библиотеками)

person Lukas Eder    schedule 15.12.2017

Невозможно объявить тип unsigned short, но в моем случае мне нужно было получить беззнаковое число, чтобы использовать его в цикле for. В классе Short есть метод toUnsignedInt, который возвращает аргумент, преобразованный в int беззнаковым преобразованием:

short signedValue = -4767;
System.out.println(signedValue ); // prints -4767

int unsignedValue = Short.toUnsignedInt(signedValue);
System.out.println(unsingedValue); // prints 60769

Подобные методы существуют для Integer и Long:

Integer.toUnsignedLong

Long.toUnsignedString: В этом случае он попадает в String, потому что нет большего числового типа.

person Aldo Canepa    schedule 01.03.2021

В Java нет беззнаковых типов. Для чего тебе это?

Однако в Java есть «байтовый» тип данных.

person CBFraser    schedule 03.12.2009
comment
байт - 8 бит, короткий - 16 бит ... не думаю, что байт будет работать :-) - person TofuBeer; 03.12.2009
comment
Я хотел бы построить многомерный массив, например, с 10000 * 10000 записей коротких чисел ... вот почему я подумал о беззнаковых шортах для выделения меньшего объема памяти - person maiky; 04.12.2009
comment
Спасибо за исправление, TofuBeer. Думаю, слишком быстро на розыгрыше. - person CBFraser; 04.12.2009
comment
Имеет смысл, @maiky. Кроме того, если вы беспокоитесь о памяти, вы, вероятно, могли бы избавиться от уловок с разреженными матрицами, если ожидаете, что много записей в вашем массиве будут нулевыми. - person CBFraser; 04.12.2009
comment
Байт в java тоже подписан по какой-то странной причине. - person 9point6; 02.05.2012

Вы можете создать класс ShortUnsigned и определить методы для тех операторов, которые вам нужны. Вы не сможете ни перегрузить +, - и другие на них, ни выполнить неявное преобразование типов с другими примитивными или числовыми типами объектов, увы.

Как и некоторые другие респонденты, мне интересно, почему у вас острая потребность в беззнаковых коротких строках, которые не могут быть заполнены никаким другим типом данных.

person Carl Smotricz    schedule 03.12.2009

Простая программа, показывающая, зачем нужны беззнаковые числа:

package shifttest;
public class ShiftTest{
    public static void main(String[] args){
        short test = -15000;
        System.out.format ("0x%04X 0x%04X 0x%04X 0x%04X 0x%04X\n",
            test, test>>1, test>>2, test>>3, test>>4);
    }
}

Результаты:

0xC568 0xFFFFE2B4 0xFFFFF15A 0xFFFFF8AD 0xFFFFFC56

Теперь для тех, кто не относится к системным типам:

JAVA выполняет арифметический сдвиг, потому что операнд подписан, однако бывают случаи, когда логический сдвиг был бы уместен, но JAVA (в частности, Sun) сочла это ненужным, слишком плохо для нас из-за своей близорукости. Shift, And, Or и Exclusive Or - это ограниченные инструменты, когда все, что у вас есть, - это более длинные числа со знаком. Это особая проблема при взаимодействии с аппаратными устройствами, которые говорят «НАСТОЯЩИЕ» компьютерные биты, составляющие 16 или более бит. Работа "char" не гарантируется (теперь она имеет ширину два байта), но для некоторых восточных языков, основанных на gif, таких как китайский, корейский и японский, требуется как минимум 3 байта. Я не знаю, сколько языков требуется в стиле Sandscript. Количество байтов зависит не от программиста, а от комитета по стандартам JAVA. Таким образом, использование char в качестве 16 бит сопряжено с риском для нисходящего потока. Для безопасного внедрения неподписанных шорт JAVA, as special class - лучшее решение, основанное на вышеупомянутой неоднозначности. Обратной стороной класса является невозможность перегрузить математические операции для этого специального класса. Многие участники этой ветки точно указали на эти проблемы, но мой вклад - это рабочий пример кода и мой опыт работы с 3-байтовыми языками gif на C ++ под Linux.

person Patrick Ireland    schedule 01.10.2013
comment
Вы можете использовать System.out.format ("0x%04X 0x%04X 0x%04X 0x%04X 0x%04X\n", test, test & 0xffff >> 1, test & 0xffff >> 2, test & 0xffff >> 3, test & 0xffff >> 4);. Это даст вам короткую смену без знака. Однако это добавляет 1 операцию (побитовое &) к каждому дерьму. - person CITBL; 05.11.2013
comment
В Java есть логический оператор сдвига вправо >>>. Кроме того, char никогда не изменит свой размер. - person Aleksandr Dubinsky; 05.09.2017

person    schedule
comment
Привет, добро пожаловать в Stack Overflow. Этот ответ может быть правильным, но его можно улучшить несколькими способами: 1.) было бы полезно, если бы вы объяснили, что происходит в коде. Как код решает проблему OP? и 2.) поскольку это довольно старый вопрос, что в вашем ответе еще нет в существующих ответах? - person MyStackRunnethOver; 11.12.2018