Java에서 서명되지 않은 int 선언


316

Java에서 서명되지 않은 int를 선언하는 방법이 있습니까?

또는 질문도 다음과 같이 구성 될 수 있습니다. 서명되지 않은 Java는 무엇입니까?

Java의 구현을보고있는 컨텍스트를 알려줍니다 String.hashcode(). 정수가 32 unsigned int이면 충돌 가능성을 테스트하고 싶었습니다.


7
Java에는 서명되지 않은 유형이 없습니다.
앤드류 로그 비 노프

1
이 게시물이 도움이 될 수 있습니다 stackoverflow.com/a/4449161/778687
tusar

2
AFAICT 방법이 아닌 것 같습니다. 관련 : stackoverflow.com/questions/430346/…
James Manning

11
달성하려는 목적에 따라 다릅니다. 대부분의 경우 Java의 모든 정수가 서명됩니다. 그러나 특정한 경우 부호있는 정수를 부호없는 것으로 취급 할 수 있습니다 . >>>대신 연산자를 사용하여 부호 확장없이 오른쪽으로 이동할 수 있습니다 >>.
dasblinkenlight

답변:


310

Java에는 부호없는 정수에 대한 데이터 유형이 없습니다 .

큰 값을 저장해야하는 경우 long대신 대신을 정의 할 수 있습니다 int.

부호없는 정수를 부호없는 것처럼 사용할 수도 있습니다. 2의 보수 표현의 이점은 부호있는 정수와 부호없는 정수에 대해 2 진 레벨에서 대부분의 연산 (더하기, 빼기, 곱하기 및 왼쪽 시프트와 같은)이 동일하다는 것입니다. 그러나 몇 가지 작업 (분할, 오른쪽 이동, 비교 및 ​​캐스팅)은 다릅니다. Java SE 8부터 Integer클래스의 새로운 메소드를 사용하면 int데이터 유형 완전히 사용하여 부호없는 산술을 수행 할 수 있습니다 .

Java SE 8 이상에서 int 데이터 유형을 사용하여 최소값 0과 최대 값 2 ^ 32-1을 갖는 부호없는 32 비트 정수를 나타낼 수 있습니다. 정수 클래스를 사용하여 int 데이터 유형을 부호없는 정수로 사용하십시오. 같은 정적 방법 compareUnsigned, divideUnsigned등은 부호없는 정수에 대한 산술 연산을 지원하는 정수 클래스에 추가되었다.

참고이 int선언되었지만 부호없는 산술에서 이러한 방법을 사용하여 현재 가능한 경우 변수가 여전히 서명 Integer클래스를.


11
공평하게 말하면, 많은 프로젝트에서 기술 요구 사항은 엄격하지 않으며 실제로 그러한 메모리를 "폐기"시킬 여유가 있습니다.
Simeon Visser 2018 년

6
나는 또한 Java의 원래 목적을 이해합니다. 그러나 예를 들어 스마트 폰은 추가 메모리로 처리하지 않습니다. 그리고 그들은 내가 아는 한 일반적으로 Java를 사용합니다. 그러나 Java 프로그래머와 다른 사람들 사이의 전쟁을 시작하고 싶지 않습니다.
Tomáš Zato-복원 모니카

122
나에게 이것은 단지 돈을 낭비하는 경우가 아닙니다. 비트 레벨에서 작업 할 때 서명되지 않은 작업은 작업하기가 더 쉽습니다.
Cruncher

24
Java 8부터는 더 이상 사실이 아닙니다 . Java SE 8 이상에서 int데이터 유형을 사용하여 최소값 0과 최대 값이 있는 부호없는 32 비트 정수를 나타낼 수 있습니다 2^32-1. - 참조 docs.oracle.com/javase/tutorial/java/nutsandbolts/...docs.oracle.com/javase/8/docs/api/java/lang/Integer.html
8bitjunkie

2
@ 7SpecialGems : 해당 정보를 포함하도록 답변을 업데이트했습니다. 즉, 부호없는 정수를 선언하거나 음수 값을 제외 할 수는 없으며 int다양한 방법을 사용하여 부호없는 것처럼 사용할 수 있습니다.
Simeon Visser

70

1
@stas 서명되지 않은 데이터 유형을 사용할 수있는 능력을 사용하는 것보다 사용법을 이해하는 데 어려움이 있습니다. 온라인에서 읽은 다양한 출처에서 최대 값을 넓히는 것을 중심으로 암시 적이며 내재적으로 양수임을 보증합니다. 내 이해가 정확합니까, 아니면 다른 중요한 이유가 있습니까? 또한 이제 IntegerJava 8 의 클래스에서 부호없는 int를 사용할 수있게 되었으므로 공간과 속도의 차이 만 있습니다 (C / C ++에서는 기본이므로 Java에서는 전체 개체 래퍼 임)
Abdul

2
@Abdul-비트 수준에서 작업 할 때 (일반적으로 하드웨어와 인터페이스하기 때문에) 특정 방식으로 동작하려면 값을 사용해야합니다. 즉-11111111에서 00000000 등으로 롤오버합니다. 부호없는 대신 부호를 사용하면 CRC 계산 등이 중단 될 수 있습니다. 쇼 스토퍼가 아니며 시간 낭비입니다.
Lorne K

3
@Lonne K : Java에서는 int서명되어 있어도 롤오버됩니다. 서명되지 않은 롤오버가 발생하는 C / C ++이지만 오버플로시 서명되지 않은 "정의되지 않은 동작"이 발생합니다. "롤오버"가 유일한 관심사 인 경우 서명하지 않아도됩니다. 그래서 CRC 루틴 등이 추가 노력없이 Java에서 작동하는 것 같습니다. 이것이 새로운 API가 구문 분석, 형식화, 비교, 나누기 및 나머지 만 추가하는 이유입니다. 다른 모든 연산, 즉 모든 비트 조작뿐만 아니라 더하기, 빼기, 곱하기 등은 어쨌든 올바른 일을하고 있습니다.
Holger

4
@Ciprian Tomoiaga : 롤오버를 추가하기 위해 입력의 비트 패턴과 결과는 부호있는 숫자 또는 부호없는 숫자로 해석되는지 여부에 따라 달라지지 않습니다. 인내심이 있다면, 모든 2⁶⁵ 조합으로 시도해 볼 수 있습니다…
Holger

3
설명을위한 @Holger 감사합니다! 실제로 우리가 실제로 2의 보수를 사용하는 이유가 밝혀졌습니다. 나는 그것을 시도 않았다 일부 ^ 2 ^ 8 조합
치프 리안 Tomoiagă에게

66

int의 값이 부호 또는 부호 없는지 여부는 비트가 해석되는 방법에 따라 다릅니다. Java는 비트를 부호있는 값으로 해석합니다 (부호없는 프리미티브가 없음).

부호없는 값으로 해석하려는 정수가있는 경우 (예 : 부호없는 값이 들어있는 DataInputStream에서 정수를 읽는 경우) 다음 트릭을 수행 할 수 있습니다.

int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffl;

16 진 리터럴은 int 리터럴이 아닌 긴 리터럴이어야하므로 끝에 'l'이 있어야합니다.


3
나에게 이것은 가장 좋은 대답이다 ... 내 데이터는 4 또는 8 바이트를 가질 수있는 NFC 카드 UID에서 온다 ... 4 바이트의 경우 부호없는 int로 캐스팅해야했고, 나는 그것을 할 수 없었다. 64 비트 데이터가 아니기 때문에 ByteBuffer.getLong을 사용하십시오. 감사.
Loudenvier

왜 길어야합니까? 0xFFFFFFint를 수행 하고 유지할 수 없습니까 ?
Displee

19

우리는 모델 부호 번호를 필요로 MySQL을의 부호 TINYINT, SMALLINT, INT, BIGINTjOOQ 우리가 만든 이유는, jOOU , 자바 부호없는 정수 숫자 유형의 래퍼 최소한의 라이브러리를 제공합니다. 예:

import static org.joou.Unsigned.*;

// and then...
UByte    b = ubyte(1);
UShort   s = ushort(1);
UInteger i = uint(1);
ULong    l = ulong(1);

이러한 모든 유형은 확장 java.lang.Number되어 고차 기본 유형 및로 변환 될 수 있습니다 BigInteger. 도움이 되었기를 바랍니다.

(면책 조항 : 나는이 라이브러리 뒤에있는 회사에서 일합니다)


이것은 매우 편리하게 들립니다! 언급 해 주셔서 감사합니다. :)
Lucas Sousa

7

부호없는 숫자의 경우 Guava 라이브러리 에서 다음 클래스를 사용할 수 있습니다 .

다양한 작업을 지원합니다.

  • ...을 더한
  • 마이너스
  • 타임스
  • 모드
  • 로 나눈

현재 누락 된 것으로 보이는 것은 바이트 시프트 연산자입니다. 필요한 경우 Java에서 BigInteger를 사용할 수 있습니다.



2

아마도 이것이 당신이 의미 한 것입니까?

long getUnsigned(int signed) {
    return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
  • getUnsigned(0) → 0
  • getUnsigned(1) → 1
  • getUnsigned(Integer.MAX_VALUE) → 2147483647
  • getUnsigned(Integer.MIN_VALUE) → 2147483648
  • getUnsigned(Integer.MIN_VALUE + 1) → 2147483649

if 문 대신 삼항 연산자를 사용하여 게으른 타이핑을 위해 두 번째 성능 시간을 희생합니다. 안좋다. (
kidding

5
당신은 정말로 생각 2 * (long) Integer.MAX_VALUE + 2하는 것보다 이해하기 쉽다고 생각 0x1_0000_0000L합니까? 그런 점에서 왜 간단하지 return signed & 0xFFFF_FFFFL;않습니까?
Holger

2

값을 사용하기 전에 값에 대해 "논리적 AND"를 수행하여 서명 문제를 처리 할 수있는 것 같습니다.

예 (의 값 byte[] header[0]0x86) :

System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));

결과:

Integer -122 = 134

2

여기에 좋은 답변이 있지만 비트 연산에 대한 데모는 보이지 않습니다. Visser (현재 허용되는 답변)와 같이 Java는 기본적으로 정수에 서명합니다 (Java 8에는 부호없는 정수가 있지만 사용하지는 않았습니다). 더 이상 고민하지 않고 해보자 ...

RFC 868 예

부호없는 정수를 IO에 작성해야하는 경우 어떻게됩니까? 실제 예는 RFC 868 에 따라 시간을 출력하려는 ​​경우 입니다. 여기에는 1900 년 1 월 1 일 오전 12시 이후의 초 수를 인코딩하는 32 비트, 빅 엔디안, 부호없는 정수가 필요합니다. 어떻게 인코딩 하시겠습니까?

다음과 같이 서명되지 않은 32 비트 정수를 만드십시오.

4 바이트 (32 비트)의 바이트 배열 선언

Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)

그러면 배열이 초기화 됩니다. Java에서 바이트 배열이 0으로 초기화됩니까?를 참조하십시오 . . 이제 배열의 각 바이트를 빅 엔디안 순서로 정보를 채워야합니다 (혹은 혼란을 피하려면 리틀 엔디안). 시간이 포함 된 long (긴 정수는 Java에서 64 비트 길이)이라고 가정하고 secondsSince1900(첫 번째 32 비트 가치 만 사용하고 Date는 1970 년 1 월 1 일 오전 12:00을 참조한다는 사실을 처리했습니다) 논리 AND를 사용하여 비트를 추출하고 해당 비트를 바이트로 강제 변환 될 때 무시되지 않는 위치 (숫자)로, 빅 엔디안 순서로 이동할 수 있습니다.

my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed

우리 my32BitUnsignedInteger는 이제 RCF 868 표준을 준수하는 부호없는 32 비트, 빅 엔디안 정수와 같습니다. 예, long 데이터 유형은 부호가 있지만 secondsSince1900은 하위 32 비트 만 사용한다고 가정했기 때문에 그 사실을 무시했습니다. long을 바이트로 압축하기 때문에 2 ^ 7보다 높은 모든 비트 (16 진수의 처음 두 자리)는 무시됩니다.

소스 참조 : Java Network Programming, 4th Edition.


1

이 코드를 작성하면 "this.altura"를 음수에서 양수로 변환합니다. 이것이 도움이 필요한 사람을 돕기를 바랍니다.

       if(this.altura < 0){    

                        String aux = Integer.toString(this.altura);
                        char aux2[] = aux.toCharArray();
                        aux = "";
                        for(int con = 1; con < aux2.length; con++){
                            aux += aux2[con];
                        }
                        this.altura = Integer.parseInt(aux);
                        System.out.println("New Value: " + this.altura);
                    }

-19

Math.abs (number) 함수를 사용할 수 있습니다. 양수를 반환합니다.


12
nitpick : 전달하지 않는 경우MIN_VALUE
Dennis Meng

2
@ kyo722 서명되지 않은 프리미티브 범위에서 양의 값을 반환한다고 상상할 수 없습니다.
Florian R. Klein

1
nitpick # 2 : 통과하면 안됩니다0
genisage
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.