Java 8 ve Java 9'da işaretsiz Tamsayı nasıl kullanılır?


82

Oracle "İlkel veri türleri" sayfasında , Java 8'in imzalanmamış girişler ve uzunlar için destek eklediğinden bahseder:

int: Varsayılan olarak, intveri türü minimum değeri −2 31 ve maksimum değeri 2 31 −1 olan 32 bitlik işaretli ikiye tümleyen bir tamsayıdır . Java SE 8 ve sonrasında, intminimum değeri 0 ve maksimum değeri 2 32 −1 olan işaretsiz 32 bitlik bir tamsayıyı temsil etmek için veri türünü kullanabilirsiniz . Veri türünü işaretsiz bir tamsayı olarak Integerkullanmak için sınıfı kullanın int. Daha fazla bilgi için Sayı Sınıfları bölümüne bakın. İşaretsiz tamsayılar için aritmetik işlemleri desteklemek için sınıfa compareUnsigned, divideUnsignedvb. Gibi statik yöntemler eklenmiştir Integer.

long: longVeri türü 64-bit ikinin tümleyen tamsayısıdır. İşaretin longminimum değeri −2 63 ve maksimum değeri 2 63 −1'dir. Java SE 8 ve sonrasında, minimum değeri 0 ve maksimum değeri 2 64 −1 olan longişaretsiz 64 biti temsil etmek için veri türünü kullanabilirsiniz . longİnt tarafından sağlananlardan daha geniş bir değer aralığına ihtiyacınız olduğunda bu veri türünü kullanın. LongSınıfı da metotlar gibi içerdiği compareUnsigned, divideUnsignedimzasız için aritmetik operasyonları desteklemek için vb long.

Bununla birlikte, işaretsiz bir uzun veya tamsayı bildirmenin bir yolunu bulamadım. Örneğin aşağıdaki kod, aralık içinde olması gerektiğinde (atanan değer tam olarak 2 64 −1) "değişmez değer aralık dışında" (elbette Java 8 kullanıyorum) derleyici hata mesajını verir. :

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

Öyleyse, işaretsiz bir int veya long belirtmenin herhangi bir yolu var mı?


2
Java 8'de Long.MAX_VALUE sabitinizde ne döndürülür?
Bruno Franco

21
İşaretsiz tam sayı veya işaretsiz uzun tip yoktur. Yeni yöntemlerden birini kullanırsanız, bu yöntem 32 bitlik veya 64 bitlik bir tamsayıya işaretsizmiş gibi davranır. Fakat hepsi bu. Değişkenin türü hala imzalı olacak ve onu işaretsiz bir sayı olarak kullandığınızı hatırlamak size kalmıştır. İmzasız değişmezler eklemediler, ancak yeteri kadar insan onları rahatsız ederse belki onları Java 9'a eklerler. :)
ajb

5
Yeni yöntemler eklemek dışında hiçbir şeyi değiştirmediler.
Hot Licks

4
Anlayabildiğim kadarıyla, yaptıkları tek şey işaretsiz değerleri döndürebilen, ancak işaretsiz değerleri bildirmenize izin vermeyen yöntemler eklemek oldu. Bana sorarsan biraz aptalca ve gerçek bir acı. Merak ediyorum, bir yolun Integer.divideUnsigned parametresini kullanıp kullanmayacağını merak ediyorum. Anladığım kadarıyla işe yarayacaktı, ama işleri yapmanın gerçekten aptalca bir yolu gibi görünüyor.
cluemein

@ajb Java'da imzalanmamış düzgün bir şekilde görmek için "dinleme" sürecinde nasıl yardımcı olabilirim? :)
Matthieu

Yanıtlar:


52

Gönderdiğiniz belgelere ve bu blog gönderisine göre - imzasız int / long ve imzalı olan arasında ilkel bildirirken hiçbir fark yoktur. "Yeni destek", Integer ve Long sınıflarındaki statik yöntemlerin eklenmesidir, örn. Integer.divideUnsigned . Bu yöntemleri kullanmıyorsanız, 2 ^ 63-1'in üzerindeki "işaretsiz", negatif bir değere sahip düz eski bir uzunluktur.

Hızlı bir gözden geçirmeden, uzunlar için +/- 2 ^ 31-1 veya +/- 2 ^ 63-1 dışındaki aralıkta tamsayı sabitleri bildirmenin bir yolu yokmuş gibi görünüyor. Aralık dışı pozitif değerinize karşılık gelen negatif değeri manuel olarak hesaplamanız gerekir.


88

Java 8'de bile longve inthala imzalı olsa bile , yalnızca bazı yöntemler onlara imzasızmış gibi davranır . Böyle imzasız longbirebir yazmak istiyorsanız , şunları yapabilirsiniz:

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
Bununla gördüğüm bir gözlem, sıralamanın bozuk olmasıdır. Bazı sistemlerden imzasız uzun bir süre alırsam (bu arada Twitter bu tür kimlikler sağlar) ve bunları sıralamak isteseydim, belki de kronolojik olduklarını bildiğim için, o zaman Long.MAX_VALUE aslında 0'dan önce negatif olarak görünecektir. Java uygulaması ile :-(. Bunun yerine, işaretsiz 0 eşlemesini imzalı Long.MIN_VALUE olarak alacak şekilde aşağı kaydırması gerekir.
David Smiley

10
@DavidSmiley İyi nokta. İmzasız uzunları sıralamak için Long.compareUnsigned kullanın veya bu yöntemi işlevleri sıralamak için karşılaştırıcı olarak
geçirin

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
     */

10
Sadece oraya kod atmakla kalmamalı, biraz açıklama eklemelisiniz.
cluemein

22

Java 8 veya Java 9'da işaretsiz bir long veya int belirtmenin bir yolu yoktur . Ancak bazı yöntemler onları imzasızmış gibi ele alır, örneğin:

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

ancak bu, değişkenin açıklaması değildir .


3
Ben neden olmasın. kolayca uint ve ulong türleri
ekleyebilirlerdi

@docesam bu ve bu belgede ayrıntılı açıklamadır. kısaca, Tamsayı sınıfına sadece işaretsiz manipülasyon için bir yöntem eklenmiştir. ve kolayca
ekleyebilselerdi

@ Ladislav DANKO sağduyulu insanlar var ve diğer adamlar var. Bu durumda - ihtiyatlı olup olmadığından emin değilim, ama benim izlenimim kehanet o kadar ihtiyatlı değil.
EKanadily

1
@docesam Hayır, "uint ve ulong türlerini kolayca ekleyemezler". Bu, JLS, JVM spesifikasyonu, JNI, birçok kütüphanenin (java.util.Arrays gibi), yansımanın ve çok daha fazlasının elden geçirilmesini gerektirir.
Nayuki

1
@ Michaelangel007 Merhaba, sanırım bu konuya farklı arka plan varsayımlarıyla yaklaşıyoruz. Bana bir e-posta atarsan ayrıntılar hakkında konuşur muyuz?
Nayuki

4

Bir üçüncü taraf kitaplığı kullanarak bir seçenek ise, orada jOOU (kütüphane kapalı bir dönüş jOOQ ), Java işaretsiz tamsayı numaraları için türleri sarıcı teklifler. Bu, imzasız türler için ilkel tür (ve dolayısıyla bayt kodu) desteğine sahip olmakla tam olarak aynı şey değildir, ancak belki de kullanım durumunuz için yeterince iyidir.

import static org.joou.Unsigned.*;

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

Bu türlerin tümü genişler java.lang.Numberve üst düzey ilkel türlere dönüştürülebilir ve BigInteger.

(Sorumluluk reddi: Bu kütüphanelerin arkasındaki şirket için çalışıyorum)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.