15 Temmuz 2018 Pazar

BigInteger Sınıfı

Giriş
Şu satırı dahil ederiz
import java.math.BigInteger;
Sınıf immutable. Aynı string sınıfında olduğu gibi her işlem yeni bir nesne döndürür. Yani sonuçları yeni bir nesneye atayarak alabiliriz.
bigInteger = bigInteger.add(value);
JVM Instrinsics (İçsel)
Bu sınıfın daha hızlı çalışması için JVM Intrinsics kullanılabilir.

Veritabanı 
Bu sınıf büyüyebilen bir non-sparse byte vector içerir. Dolayısıyla teorik olarak belleğin izin verdiği kadar büyük sayılar tutabilir.

How do computers perform operations on numbers that are larger than 64 bits? yazısında bir örnek var.

BigInteger sınıfını veritabanında saklamak için SQL Server'da varbinary (16) veya varbinary (32) genellikle yeterli olur.

Hazır değerler
0,1,2 ve 10 değerleri hazır geliyor.
/**
 * The BigInteger constant zero.
 *
 * @since   1.2
 */
public static final BigInteger ZERO = new BigInteger(new int[0], 0);

/**
 * The BigInteger constant one.
 *
 * @since   1.2
 */
public static final BigInteger ONE = valueOf(1);

/**
 * The BigInteger constant two.  (Not exported.)
 */
private static final BigInteger TWO = valueOf(2);

/**
 * The BigInteger constant ten.
 *
 * @since   1.5
 */
public static final BigInteger TEN = valueOf(10);
constructor - Byte Array
İmzası şöyle.
BigInteger (byte [] val);
Açıklaması şöyle.
Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger.
Şöyle yaparız.
byte[] bytesArray = {7,34};
BigInteger bytesTointeger= new BigInteger(bytesArray);
constructor - Random Number Generator
Çok saçma gelebilir ama böyle bir constructor var. Kaç bit istediğimizi belirtip kullanıyoruz.
private final int NUMBITS = 268;

public void test() {
    Random r = new Random();
    BigInteger b = new BigInteger(NUMBITS, r);
    System.out.println(b);
}
constructor - signum + magnitude
Neden BigInteger nesnesine 1 geçtiğimizi n açıklaması şöyle. Yani byte[] nesnesini artı/eski sayı olarak değil de byte[] gibi algılaması için
Use new BigInteger(1, bytes), instead of new BigInteger(bytes), because .. the byte data type does not hold bytes but signed tiny integers [-128...127]. If the first byte is negative, the BigInteger assumes you pass a negative big integer. Just pass 1 as first parameter (signum=1).
Örnek
Şöyle yaparız. Burada byte[] ile ilklendirdiğimiz için veriyi pozitif kabul ettik
 BigInteger md5Actual = new BigInteger(1, md5Digest.digest());
constructor - String
Avogadro sayısını kullanan bir örnek
BigInteger a = new BigInteger("602200000000000000000000");
a = a.multiply(new BigInteger("2"));
System.out.println(a);
constructor - String + Radix (Taban)
İkilik tabanda yani 1 ve 0'lardan oluşan bir string varsa şöyle yaparız.
String b = "1001";
new BigInteger(b, 2);
On altılık tabanda yani hexadecimal bir string varsa şöyle yaparız.
String b = "1E99423A4E";new BigInteger(b, 16);
constructor - unsigned long
Örnek
Java'da unsigned long olmadığı için şöyle yaparız.
BigInteger result = BigInteger.valueOf(bytebuffer.getLong());
if (result.compareTo(BigInteger.ZERO) < 0) {
    result = result.add(BigInteger.ONE.shiftLeft(64));
}
Örnek
Şöyle yaparız.
new BigInteger(Long.toUnsignedString(bytebuffer.getLong()))
Örnek
Şöyle yaparız.
static BigInteger toUnsignedBigInteger(long i) {
  if (i >= 0L)
    return BigInteger.valueOf(i);
  else {
    int upper = (int) (i >>> 32);
    int lower = (int) i;

    // return (upper << 32) + lower
    return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
            add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
  }
}
add metodu
BigInteger kendi içinde veriyi int[] olarak saklar. Aşağıdaki kodda görülebilir.
public BigInteger add(BigInteger val) {
    if (val.signum == 0)
        return this;
    if (signum == 0)
        return val;
    if (val.signum == signum)
        return new BigInteger(add(mag, val.mag), signum);

    int cmp = compareMagnitude(val);
    if (cmp == 0)
        return ZERO;
    int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
                       : subtract(val.mag, mag));
    resultMag = trustedStripLeadingZeroInts(resultMag);

    return new BigInteger(resultMag, cmp == signum ? 1 : -1);
}
and metodu
Bit olarak and'ler.
Örnek 1
BigInteger n = new BigInteger(numericString);
BigInteger test = n.and(n.subtract(BigInteger.ONE));
if (test.equals(BigInteger.ZERO)) {
  ...
}
Şu kod ile aynıdır.
if ((n & (n - 1)) == 0)){...}
Örnek 2
2'nin katı olduğunu anlamak için bir sayıda tek bir tane 1 biti olduğunu anlamak yeterli. Şöyle yaparız.
boolean test = x.and(x.subtract(BigInteger.ONE)).equals (BigInteger.ZERO);
bitLength metodu
Şöyle yaparız.
BigInteger x = ...;
BigInteger y = BigInteger.ZERO.setBit (x.bitLength ()/2);
compareTo metodu
Şöyle yaparız.
BigInteger x = ...;
BigInteger y = ...

if (x.compareTo(y) <= 0) {...}
divide metodu
x / div yapmak için şöyle yaparız.
BigInteger x = ...;
BigInteger div = ...;
BigInteger y = x.divide (div);
diveAndRemainder metodu
Şöyle yaparız.
BigInteger x = ...;
BigInteger y = ...;
BigInteger[] modResult = x.divideAndRemainter(y);
int ret = modResult[1].intValueExact();
BigInteger b = modResult[0];
equals metodu
Şöyle yaparız.
BigInteger x = ...;
BigInteger y = ...;
if (y.equals (x)) {...}
intValue metodu
Açıklaması şöyle
Converts this BigInteger to an int. This conversion is analogous to a narrowing primitive conversion from long to int as defined in section 5.1.3 of The Java™ Language Specification: if this BigInteger is too big to fit in an int, only the low-order 32 bits are returned. Note that this conversion can lose information about the overall magnitude of the BigInteger value as well as return a result with the opposite sign.
isProbablePrime metodu
Bu sınıfın isProbablePrime isimli ilginç bir metodu var. Değeri asal sayı değilse false döner, true dönerse asal sayı olma ihtimali vardır, yani asal sayı olduğu kesin değildir. Bu metod Fermat'nın Küçük Teoremini (Fermat's Little Theorem) kullanıyor. Bu teorem şöyle kodlanır.
def CheckIfProbablyPrime(x):
    return (2 << x - 2) % x == 1
Bu teoremde Carmichael Sayıları asal olmadıkları halde yanlış alarm veriyorlar.

longValue metodu
Şöyle yaparız.
txnRecNo.longValue();
modInverse metodu
Elimizde şu denklem olsun.
a mod x = b
x'i bulmak için şöyle yaparız.
BigInteger.valueOf(a).modInvsere (BigInteger.valueOf (b));
modPow metodu
Sayının üssünü aldıktan sonra mod işlemine gerçekleştirir. Şöyle yaparız.
BigInteger b = ...;
BigInteger b1 = b.modPow(exp, mod);
multiply metodu
Kullanılabilecek bir sürü algoritma var. Açıklaması şöyle
The list of possible algorithms for multiplication is quite long:

- Schoolbook long multiplication
Karatsuba algorithm
3-way Toom–Cook multiplication
- k-way Toom–Cook multiplication
- Mixed-level Toom–Cook
- Schönhage–Strassen algorithm
- Fürer's algorithm
Açıklaması şöyle
For Java 11 it uses:

- naive "long multiplication" for small numbers,
- Karatsuba algorithm for medium sized number, and
- 3-way Toom–Cook multiplication for large numbers.
Örnek
Şöyle yaparız.
BigInteger sum = ...;
BigInteger multiple = sum.multiply(sum);
pow metodu
Sayının üssünü hesaplar.
BigInteger b = new BigInteger(4);
b1 = b1.pow(2);
setBit metodu
bigLength() , setBit(), clearBit() gibi bitleriyle oynamamızı sağlayan faydalı metodlar var. Örnekte verilen sayıdan bir küçük ve ikinin katı olan sayı bulunuyor. Eğer girdimiz 1111 bitlerine sahipse elimize 100 bitlerine sahip bir sayı geçer
private static BigInteger getHighestPowerOf2(BigInteger bigInteger)
{
   int bitLength = bigInteger.bitLength();
   return BigInteger.ZERO.setBit(bitLength-1);
}
shifRight metodu
Örnekte kare kök alınıyor. Yine setBit ile sayının yaklaşık dötte biri ile başlıyoruz.
public static BigInteger sqrt(BigInteger x) {
    BigInteger div = BigInteger.ZERO.setBit(x.bitLength()/2);
    BigInteger div2 = div;
    // Loop until we hit the same value twice in a row, or wind
    // up alternating.
    for(;;) {
        BigInteger y = div.add(x.divide(div)).shiftRight(1);
        if (y.equals(div) || y.equals(div2))
            return y;
        div2 = div;
        div = y;
    }
}
subtract metodu
Şöyle yaparız.
BigInteger n = ...;
BigInteger test = n.subtract(BigInteger.ONE);
toByteArray metodu
Şöyle yaparız.
byte[] bytes = n.toByteArray();
toString metodu - radix
Hexadecimal olarak string'e çevirmek istersek şöyle yaparız. Bu çağrı baş tarafa 0 eklemez. Aynı problem Integer.toHexString() metodunda da var. 
n.toString(16);
Baş tarafa sıfır eklemek istersek şöyle yaparız.
String md5h = String.format("%032x",n);
valueOf metodu - long
Açıklaması şöyle. Bu yüzden long alan bir constructor metodu mevcut değil.
Returns a BigInteger whose value is equal to that of the specified long. This "static factory method" is provided in preference to a (long) constructor because it allows for reuse of frequently used BigIntegers.
Şöyle yaparız.
int num = ...;
BigInteger v = BigInteger.valueOf(num);
Şöyle yaparız.
BigInteger v = BigInteger.valueOf (2L);


4 yorum:

  1. merhaba çok teşekkürler yazınız için fakat bir sorum olacaktı bilgi güvenliği dersinde hoca bizden rsa şifreleme de d gizli anahtarını formül yardımıyla oluşturmamızı istedi ama 128 bit değerinde falan. ben bu d gizli anahtarını java da long ile oluşturamıyorum. BigIntegerı da tam anlamadım şimdi ben 128 bit bir sayı oluşturup mod alma,çarpma , asal mı gibi işlemlere tabi tutabilir miyim. ve sayiyi tam olarak nasıl oluşturabilirim

    YanıtlaSil
  2. https://gunceljava.blogspot.com/2016/06/keypairgenerator-snf.html
    ve
    https://gunceljava.blogspot.com/2019/09/rsapublickey-arayuzu.html
    yazılarına bakabilirsiniz. Belki bir fikir verir.

    YanıtlaSil
  3. 8'in katı olmayan sayıda bit saklayabilir miyiz?

    YanıtlaSil
    Yanıtlar
    1. Sınıf kendi içinde veriyi int[] olarak sakladığı için 8'in katı olmak zorunda. Ancak sınıfın string+radix alan constructor'ını kullanırsanız 8'in katı olmayan bir sayı ile ilklendirebilirsiniz. Örnekte 4 bit ile ilklendiriliyor.

      Sil