Java 8 및 Java 9에서 서명되지 않은 정수를 사용하는 방법은 무엇입니까?


81

Oracle "Primitive data types" 페이지 에서 Java 8이 서명되지 않은 int 및 long에 대한 지원을 추가한다고 언급합니다.

int: 기본적으로 int데이터 유형은 32 비트 부호있는 2의 보수 정수이며, 최소값은 −2 31 이고 최대 값은 2 31 −1입니다. Java SE 8 이상에서는 int데이터 유형을 사용하여 최소값이 0이고 최대 값이 2 32 -1 인 부호없는 32 비트 정수를 나타낼 수 있습니다 . 데이터 유형을 부호없는 정수로 사용하려면 Integer클래스를 사용 하십시오 int. 자세한 내용은 The Number Classes 섹션을 참조하십시오. 같은 정적 방법 compareUnsigned, divideUnsigned등이 첨가 된 Integer부호없는 정수에 대한 산술 연산을 지원하는 클래스.

long: long데이터 유형은 64 비트 2의 보수 정수입니다. 부호 long있는 값은 최소값 -2 63 이고 최대 값은 2 63 -1입니다. Java SE 8 이상에서는 long데이터 유형을 사용하여 long최소값이 0이고 최대 값이 2 64 -1 인 부호없는 64 비트를 나타낼 수 있습니다 . int에서 제공하는 것보다 더 넓은 값 범위가 필요한 경우이 데이터 유형을 사용하십시오. Long클래스는 방법이 좋아 포함 compareUnsigned, divideUnsigned서명에 대한 산술 연산을 지원하는 등 long.

그러나 부호없는 long 또는 정수를 선언하는 방법을 찾지 못했습니다. 예를 들어, 다음 코드는 범위 내에 있어야 할 때 "리터럴이 범위를 벗어났습니다"(물론 Java 8을 사용하고 있음)라는 컴파일러 오류 메시지를 제공합니다 (할당 된 값은 정확히 2 64 -1입니다). :

public class Foo {
    static long values = 18446744073709551615L;
    
    public static void main(String[] args){
        System.out.println(values);
    }  
}

그렇다면 unsigned int 또는 long을 선언하는 방법이 있습니까?


2
Java 8의 Long.MAX_VALUE 상수에서 반환되는 것은 무엇입니까?
Bruno Franco

21
부호없는 정수 또는 부호없는 long 유형이 없습니다. 새 메서드 중 하나를 사용하는 경우 해당 메서드는 32 비트 또는 64 비트 정수를 부호없는 것처럼 처리합니다. 하지만 그게 다입니다. 변수의 유형은 여전히 ​​서명되어 있으며 서명되지 않은 숫자로 사용하고 있음을 기억하는 것은 사용자에게 달려 있습니다. 그들은 서명되지 않은 리터럴을 추가하지 않았지만 충분한 사람들이 버그를 잡으면 자바 9에 추가 할 것입니다. :)
ajb

5
그들은 새로운 방법을 추가하는 것 외에는 아무것도 변경하지 않았습니다.
Hot Licks

4
내가 말할 수있는 한, 그들이 한 일은 서명되지 않은 값을 반환 할 수있는 메서드를 추가하는 것이지만 서명되지 않은 값을 선언하는 것을 허용하지 않습니다. 나에게 물어 보면 어리석은 일이고 진짜 고통스러워. 한 가지 방법이 Integer.divideUnsigned를 사용하는 것이 아닌지 궁금합니다. 하나의 매개 변수는 1이고 다른 하나는 부호없는 것으로 취급하려는 숫자입니다. 내가 말할 수있는 한 작동 하겠지만 일을하는 정말 어리석은 방법 인 것 같다.
cluemein

@ajb "버깅"프로세스에서 최종적으로 서명되지 않은 Java를 확인하는 데 어떻게 도움을 줄 수 있습니까? :)
Matthieu

답변:


51

게시 한 문서 와이 블로그 게시물 에 따라 서명되지 않은 int / long과 서명 된 int / long 사이의 기본 요소를 선언 할 때 차이가 없습니다. "새로운 지원"은 Integer 및 Long 클래스 (예 : Integer.divideUnsigned)에 정적 메서드가 추가 된 것입니다 . 이러한 방법을 사용하지 않는 경우 2 ^ 63-1보다 긴 "unsigned"는 음수 값을 가진 평범한 오래된 long입니다.

간단히 훑어 보면 +/- 2 ^ 31-1 또는 long의 경우 +/- 2 ^ 63-1 범위를 벗어난 정수 상수를 선언하는 방법이없는 것 같습니다. 범위를 벗어난 양수 값에 해당하는 음수 값을 수동으로 계산해야합니다.


85

음, 심지어 자바 (8)에, long그리고 int아직 서명, 일부 방법은 그들이 서명되지 않은 것처럼 그들을 치료 . 그렇게 서명되지 않은 long리터럴 을 작성 하려면 다음을 수행하십시오.

static long values = Long.parseUnsignedLong("18446744073709551615");

public static void main(String[] args) {
    System.out.println(values); // -1
    System.out.println(Long.toUnsignedString(values)); // 18446744073709551615
}

5
내가 본 관찰은 순서가 잘못되었다는 것입니다. 일부 시스템에서 서명되지 않은 long을 가져오고 (Twitter가 이러한 ID를 제공함) 정렬하고 싶을 경우, 아마도 시간순이라는 것을 알았 기 때문에 Long.MAX_VALUE 이후의 모든 것은 실제로 0 이전에 음수로 표시됩니다. . 자바의 구현 :-(로 대신 하나는 그러한 그 부호 0지도 아래를 이동해야 나타납니다 서명 Long.MIN_VALUE로부터.
데이비드 스마일

10
@DavidSmiley 좋은 지적입니다. 부호없는 long을 정렬하려면 Long.compareUnsigned를 사용 하거나 해당 메서드를 비교기로 전달하여 함수를 정렬합니다.
kajacx

26
    // Java 8
    int vInt = Integer.parseUnsignedInt("4294967295");
    System.out.println(vInt); // -1
    String sInt = Integer.toUnsignedString(vInt);
    System.out.println(sInt); // 4294967295

    long vLong = Long.parseUnsignedLong("18446744073709551615");
    System.out.println(vLong); // -1
    String sLong = Long.toUnsignedString(vLong);
    System.out.println(sLong); // 18446744073709551615

    // Guava 18.0
    int vIntGu = UnsignedInts.parseUnsignedInt(UnsignedInteger.MAX_VALUE.toString());
    System.out.println(vIntGu); // -1
    String sIntGu = UnsignedInts.toString(vIntGu);
    System.out.println(sIntGu); // 4294967295

    long vLongGu = UnsignedLongs.parseUnsignedLong("18446744073709551615");
    System.out.println(vLongGu); // -1
    String sLongGu = UnsignedLongs.toString(vLongGu);
    System.out.println(sLongGu); // 18446744073709551615

    /**
     Integer - Max range
     Signed: From −2,147,483,648 to 2,147,483,647, from −(2^31) to 2^31 – 1
     Unsigned: From 0 to 4,294,967,295 which equals 2^32 − 1

     Long - Max range
     Signed: From −9,223,372,036,854,775,808 to 9,223,372,036,854,775,807, from −(2^63) to 2^63 − 1
     Unsigned: From 0 to 18,446,744,073,709,551,615 which equals 2^64 – 1
     */

9
코드를 던지는 것이 아니라 설명을 추가해야합니다.
cluemein

20

Java 8 또는 Java 9에서 unsigned long 또는 int 를 선언 하는 방법은 없습니다. 그러나 일부 메소드는이를 서명되지 않은 것처럼 처리합니다. 예를 들면 다음과 같습니다.

static long values = Long.parseUnsignedLong("123456789012345678");

그러나 이것은 변수의 선언 이 아닙니다 .


3
나는 왜 안돼. 그들은 쉽게 UINT 및 ULONG 유형을 추가 할 수
EKanadily

에 @docesam 다큐는 자세한 설명입니다. 요컨대 Integer 클래스에 대한 서명되지 않은 조작을위한 메서드가 추가되었습니다. 그리고 그들이 쉽게 추가수 있었다면 나는 그들이 그것을하지 않을 이유를 모르겠습니다 ;-)
1ac0

@ Ladislav DANKO 신중한 사람들이 있고 다른 사람들이 있습니다. 나는-이 경우-그것이 신중한 것인지 아닌지는 확실하지 않지만, 오라클이 그렇게 신중하지 않다는 것이 나의 인상입니다.
EKanadily

1
@docesam 아니요, "쉽게 추가 된 uint 및 ulong 유형"을 가질 수 없습니다. 이를 위해서는 JLS, JVM 사양, JNI, 많은 라이브러리 (예 : java.util.Arrays), 반사 등을 정밀 검사해야합니다.
Nayuki

1
@ Michaelangel007 안녕하세요, 저는 우리가 다른 배경 가정으로이 주제에 접근하고 있다고 생각합니다. 저에게 이메일을 보내 주시면 세부 사항에 대해 얘기해 드리겠습니다.
Nayuki

4

타사 라이브러리를 사용하는 옵션 인 경우가 jOOU (에서 라이브러리 오프 스핀 jOOQ ), 자바 부호없는 정수 숫자 유형의 래퍼 이벤트. 이것은 서명되지 않은 유형에 대한 기본 유형 (따라서 바이트 코드) 지원을 갖는 것과 똑같은 것은 아니지만 아마도 사용 사례에는 충분할 것입니다.

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.

(면책 조항 : 저는이 도서관 뒤에있는 회사에서 일합니다)

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