Bildiğiniz gibi derleyiciler belli bytelarda sayıları tutabilmekte ve buna bağlı olarak sayılar çarpıldığında da bu byte sınır kadar izin vermektedirler. Örneğin çarpmak istediğimiz ve compilere input olarak girebileceğimiz 2 int sayısının çarpımı oldukça büyük olacağından derleyici bize muhtemelen çöp dönecektir. Bu yine de yapılamayacak bir durum değildir. Yine derleyicinin bize sağlamış olduğu dizilerle kolay olmasa da çok da güzel bir şekilde bu işi gerçekleştirebiliriz.
Paylaşacağım kodda tüm değişkenleri "long long int" olarak tanımladım. Nereye kadar çalıştığını görmek istedim. Ubuntuda g++ version 4.4.3'da denemelerimi gerçekleştirdim. Vektör ve dinamik bellek ayırmalar olduğu için windowsta ne tepkiler verir şuan için tahmin edemiyorum. Ama sanırım problem olmaz,zira ortada sistem call tarzı çalışması garip processler bulunmamaktadır:).
Daha önce C'de yazmıştım. Hem dağınık yazmışım hem de yeterince test etmedim, %100 doğru çalıştığından emin değilim. Bu sefer C++'da yazdım. Hem okunaklı hem açık. Özellikle vektörlerin Arraylere nazaran kolay kullanılabilirliğini farkedeceksiniz. Ekran görüntüsü ise böyledir.
Kod ise aşağıdaki gibidir. Hata durumları ve hız konusunda öneriler bekliyorum. Ayrıca çarpmadan sonra bölme işlemi nasıl olur, veya floating point çarpımları nasıl olur. Hatta bunu sadece input girilebilen bir sistem haline nasıl getirmek mümkün olur, hepsi soru işareti ?
#include <iostream>
#include <vector>
using namespace std;
int main()
{
long long int sizex = 0, sizey = 0, sizetotal;
long long int x, y, tmp;
long long int n, m, tmpx, tmpy;
vector < vector <long long int> > v;
vector < long long int > tmpvx;
vector < long long int > tmpvy;
long long int birler, onlar, k = 0;
x = 1223372036854775808;
y = 1223372036854775808;
cout <<"Compiler destekleyen byte: " << sizeof(long long int) << endl;
tmp = x;
while( tmp )
{// x sayısı kaç basamaklıdır
sizex++;
tmp /= 10;
}
tmp = y;
while( tmp )
{// y sayısı kaç basamaklıdır
sizey++;
tmp /= 10;
}// toplam basamak + 1 olası carry bit
sizetotal = sizex + sizey + 1;
v.resize(sizey + 1); // vektör malloc/realloc
for(int i = 0; i < v.size(); i++)
{
v[i].resize(sizetotal + 1); // 2D vektör yap
for(int j = 0; j < sizetotal + 1; j++)
v[i][j] = 0; // içini sıfırla
}
n = 10;
m = 1;
for(int i = 0; i < sizetotal + 1; i++)
{
if(m < x && i < sizex)
{// x sayısını basamaklarına ayır vektöre yedekle
tmpx = x%n;
tmpx = tmpx/m;
tmpvx.resize(tmpvx.size() + 1);
tmpvx[i] = tmpx;
}
if(m < y && i < sizey)
{// y sayısını basamaklarına ayır vektöre yedekle
tmpy = y%n;
tmpy = tmpy/m;
tmpvy.resize(tmpvy.size() + 1);
tmpvy[i] = tmpy;
}
m = n;
n *= 10;
}
k = 0;
for(int i = 0; i < tmpvy.size(); i++)
{
for(int j = 0; j < tmpvx.size(); j++)
{// y sayısının sondan itibaren rakamlarını x'in rakamları ile çarpıyoruz
tmp = tmpvx[j] * tmpvy[i];
onlar = tmp / 10;
birler = tmp % 10;
v[i][j + k] += birler;
v[i][j + k + 1] += onlar;
}
for(int j = 0; j < sizetotal; j++)
{// sonucu baştan tarayıp rakam olmayanları 10'a bölüp carry olarak sağa atıyoruz
if(v[i][j] > 9)
{
tmp = v[i][j];
v[i][j] = tmp % 10;
v[i][j + 1] += tmp / 10;
}
}
k++;
}
cout<<"vektor:"<<endl;
// son işleme girmeden önceki hali - çalıştırmaya gerek yok
/*
for(int i = 0; i < sizey + 1; i++)
{
for(int j = 0; j < sizetotal + 1; j++)
cout << v[i][j] << " ";
cout << endl;
}*/
tmp = 0;
for(int i = 0; i < sizetotal + 1; i++)
{// toplama sonucunda taşmalar olabilir, Carry kontrolü yapılıyor
for(int j = 0; j < sizey; j++)
tmp += v[j][i];
v[sizey][i] = tmp % 10;
v[sizey][i + 1] += tmp / 10;
tmp = v[sizey][i + 1];
}
for(int i = 0; i < sizey + 1; i++)
{// vektörü bir bütün olarak yaz
for(int j = 0; j < sizetotal + 1; j++)
cout << v[i][j] << " ";
cout << endl;
}
cout << "Carpim Sonucu: "<<endl;
int flag = 0;
for(int i = sizetotal; i>=0; i--)
{// sonucu yaz. Baştaki gereksiz sıfırlardan arınılıyor. vektörün son satırına dikkat
if(v[sizey][i] != 0 || flag)
{
flag = 1;
cout << v[sizey][i];
}
}
cout << endl;
return 0;
}


0 yorum:
Yorum Gönder