paint-brush
Akıllı Sözleşmelerde Tamsayı Bölme Hatası Nasıl Atlanır?ile@dansierrasam79
1,822 okumalar
1,822 okumalar

Akıllı Sözleşmelerde Tamsayı Bölme Hatası Nasıl Atlanır?

ile Daniel Chakraborty6m2023/02/20
Read on Terminal Reader
Read this story w/o Javascript

Çok uzun; Okumak

Python veya Java öğrenmeye başladığınızda float veri türünü kullanacaksınız. Solidity'de imzalı veya imzasız tamsayı tipindeki sayıları kullanıyor olacaksınız. Solidity floatData tipini desteklemediğinden elde ettiğiniz sonuç aynı olmayacaktır.
featured image - Akıllı Sözleşmelerde Tamsayı Bölme Hatası Nasıl Atlanır?
Daniel Chakraborty HackerNoon profile picture
0-item
1-item
2-item

Hepimiz okulda kayan nokta sayılarını öğrendik. Ondalık noktası olmayan tam sayıların aksine.


Beş sayısının bir tam sayı, 5,43'ün ise kayan noktalı bir sayı olduğunu bilmek için matematik dehası olmanıza gerek yok. Açıkçası, hepimiz ikisi arasında net bir ayrım noktası olan ondalık sayıya aşinayız.


Elbette, kayan noktalı değişkenlerin programlama dillerinde kullanılması ve hatta günlük hesaplamalar için ne kadar gerekli olduğundan ayrı bir ilkel veri türü olarak sınıflandırılması şaşırtıcı değildir.

Programlama Dillerinde Kayan Noktalı Sayıların Kullanımı

Python veya Java öğrenmeye başladığınızda float veri türünü kullanacaksınız. Özellikle, iki kayan noktalı sayı arasında bölme işlemini gerçekleştirdiğinizde.


Python'da, kayan noktalı bir sayı bildirmeniz gerekmese bile, bu sayıların ikisini bölmek, aşağıda gösterildiği gibi aynı veri türünde bir sayıyla sonuçlanabilir:


İki kayan noktalı sayıyı bölmek için Python programı


Kullanılan tüm değişkenler için 'float' ilkel veri türünü açıkça bildirmemiz gerekse bile, aynı sonucu Java'da da üretebiliriz.


İki kayan noktalı sayıyı bölmek için Java programı


Anlaşılabileceği gibi, bu tür bir hesaplama bir dizi uygulama için gereklidir ve kayan nokta sayılarıyla yapılan işlemlerin her iki programlama dilinde de bir özellik olarak mevcut olmasının nedeni tam olarak budur.


Oldukça farklı bir şekilde, eğer Solidity'yi öğreniyorsanız, onun kayan noktalı sayı veri tipini içermediğini fark etmiş olmalısınız.

Solidity, Kayan Nokta Sayıları Olmadan İşlemleri Nasıl Gerçekleştirir?

Bunun yerine, eğer Solidity'de herhangi bir kod yazdıysanız, imzalı veya imzasız tamsayı tipindeki sayıları kullanıyor olacaksınız.


Dolayısıyla, önceki bölümde gösterildiği gibi aynı hesaplamayı (beş bölü ikiye) yapmak istiyorsanız, akıllı sözleşmenin bir parçası olarak şu şekilde görünecektir:


Tamsayı Bölme Hatası - Sağlamlıkta Akıllı Sözleşme


Ancak Solidity, float veri tipini desteklemediğinden elde ettiğiniz sonuç aynı olmayacaktır. En azından henüz değil.


getResult işlevi


Özellikle, Sağlamlık sonucu sıfıra doğru yuvarlayacaktır. Bu durumda ve yukarıda gösterildiği gibi, iki değeri elde edilecektir. Bunu her iki sayının modülo işlemi olarak düşünün.


Normal şartlarda bu çok önemli olmasa da, sonucun hesaplamada hataya yol açabileceği zamanlar vardır. Bu nedenle bölme işleminden mümkün olduğunca kaçınılması veya ertelenmesi tavsiye edilir.

Tam Sayı Bölme Hatasına İlk Bakışınız

Okuldaki BODMAS kuralı tüm matematik öğrencilerinin çarpmadan önce bölme hesaplamasını yapmasını gerektirse bile, Solidity'de tamsayı bölme işlemi yapmanız gerekiyorsa bu önerilmez.


Üç sayıyla çarpma ve bölme işleminin neden yapıldığını bu basit örnekle öğrenelim:


Üç Sayıyı Çarp ve Böl - Sağlamlıkta Akıllı Sözleşme


Akıllı sözleşmeyi dağıtırken bir, üç ve beş rakamlarını girerseniz getResult ve getResult2 işlevleri için aynı değeri elde etmelisiniz, değil mi?


Basit bir hesap makinesi kullanırsanız, kayan nokta değerlerinin yokluğu sayesinde, Katılık'ta bire dönüşen 1,666 kayan nokta değerini elde etmelisiniz.


Ne yazık ki, aşağıda gösterildiği gibi getResult ve getResult2 işlevlerinin sonuçlarını kontrol ettiğinizde olan şey bu değildir:


getResult ve getResult2 sonuçları


Önce bölme işlemini yaparsak nihai sonuç sıfır olur. Beklenen bir değerinin aksine, getResult işlevinde bu işlemi sonuna kadar ertelediğinizde.


Anlayabileceğiniz gibi, bu değeri kayan değerlerin yokluğunu tahmin ederek hesaplamış olsak bile, yine de hassasiyet kaybına neden olabilecek bir hata ortaya çıkıyor. Bu da kolaylıkla atlatılabilecek bir ekonomik kayıp anlamına gelebilir.


Peki tamsayı bölme hatasını nasıl önleyebiliriz? Daha da önemlisi, hesaplamalarımızın hassasiyetini nasıl artırırız? Bunu yapmanın en yaygın üç yolunu bulalım.

Tamsayı Bölme Hatasını Önlemenin 3 Yolu

Bu hatayı aşmak için çeşitli yaklaşımlar olduğu göz önüne alındığında, en basit düzeltmeyle başlayalım ve bir gün daha uğraşmadan önce birkaç yaklaşıma daha bakalım.


Yöntem 1: Çarpan kullanın

Şimdi, bölme işlemini en sona koymanın yanı sıra, hatalarla veya kesin olmayan değerlerle karşılaşmamanızı sağlamanın bir yolu da çarpan kullanmaktır. Aşağıdaki örnekte, daha önce kullandığımız üç sayıyla birlikte 100 çarpanını kullanacağız.


Çarpan kullanma - Sağlamlıkta Akıllı Sözleşme


Şimdi, sözleşmeyi aşağıdaki kodla dağıttığınızda ve her iki işlevi de çağırdığınızda çıktı şu olur:

Çarpan kullanma - getResult ve getResult2 değerleri


İstenilen çıktı 1.666 veya 166/100 olduğundan çarpan üç sayı ile birlikte çalıştığında getResult2 değerinin bize gerekli doğruluğu sağladığını görebiliriz. Tabii çarpanı getResult fonksiyonundaki gibi kullanmazsanız 1 elde edersiniz.


Solidity'yi kullandığınızda varsayılan olarak beklendiği gibi 0,666'nın sonuçtan kesildiği yer. Yani bu değeri elde etmek için tek yapmanız gereken sonucu çarpana bölmek.


Bildiğiniz gibi, hem imzalı hem de imzasız tamsayılar durumunda yuvarlama söz konusu olduğunda Solidity sıfıra doğru hareket eder; bu nedenle, aşağıdaki kodu eksi bir argümanla dağıtıp çalıştırdığınızda, bu düzeltme işaretli tamsayılar durumunda da işe yarar. , üç ve beş:


İmzalı tamsayılar için çarpan kullanma - Solidity'de Akıllı Sözleşme


İşaretli tamsayılar için işlevler tarafından oluşturulan değerlere gelince, bunlar şunlardır:


İmzalı tamsayılar için çarpan kullanma - Solidity'de Akıllı Sözleşme


Açıkçası, bir çarpan kullanarak işaretli tamsayılar için de kesinliği koruyabiliyoruz. Ancak daha sonra bakacağımız işaretli tam sayıları yuvarlamanın kesin bir yolu var.


Yöntem #2: İmzalı tamsayılar için taban bölümünü kullanın

Şimdi aşağıdaki sayı doğrusuna bakıldığında iki işaretsiz tam sayı arasında tamsayı bölme işleminin sonucu sıfıra yakın yuvarlanır. 1.666 elde edilmesi durumunda olduğu gibi, Solidity bunu daha küçük bir sayı olan 1'e yuvarlar.


Sayı doğrusu


Ancak işaretli tamsayılar söz konusu olduğunda -1,6666 sonucu iki sayıdan büyük olan -1'e yuvarlanacaktır. Bu nedenle, Solidity'de varsayılan olarak uygulanan sıfıra yuvarlatılmış bölmenin aksine burada taban bölmesi uygulanmalıdır. Tabii ki kesinlik adına.


İmzalı tamsayılar için kat bölme işlemini gerçekleştirme


Float veri türü mevcut olsaydı -1,666 değeri hesaplanır. Solidity bunu -1'e yuvarlarken, imzalı tam sayılara taban bölümü uygulamak bunu -2'ye düşürecektir.


getResult ve getResult2 işlevlerini çağırdığınızda eksi bir, üç ve beş argümanı için aşağıda gösterilen değeri elde ederiz:


getResult2 doğru kat bölümü sonuçlarını verir


Gördüğünüz gibi, getResult değeri sıfıra yuvarlama yaklaşımını kullanarak hesaplarken, getResult2 bunu kat bölümü sayesinde buradaki en küçük tam sayıya yuvarlar.


Yöntem #3: ABDKMath64x64 kitaplığını kullanın

Şimdi son yöntem olarak bölme işlemlerinin sonucunu sabit nokta sayılarına dönüştüren ABDKMath64x64 kütüphanesini kullanacağız.


Yine, bu kütüphaneyi kullanmanın, Solidity'de varsayılan olarak mevcut olan sıfıra doğru yuvarlama yönteminin aksine doğruluğu arttırdığı söyleniyor. Çıktıyı anlayabilmek için add işleminin sonuçlarını aşağıda gösterildiği gibi div fonksiyonuyla karşılaştıralım:


ABDK kütüphanesini kullanma


Akıllı sözleşmeyi dağıtırken 1, 1 ve 1 argümanlarını eklediğinizde aşağıda gösterilen değerleri elde edersiniz:

ABDK kütüphanesini kullanma - Çıktı


Ekleme fonksiyonunun iki tamsayı değerini döndürmesi ve üç argümanın toplamının bu kadar olması sürpriz olmamalıdır. Div işlevine gelince, imzalı 64,64 bitlik sabit nokta sayısını temsil eden ve olağan sayı işlemlerini gerçekleştirebileceğiniz bir int 128 değeri döndürülür.

Dikkate Alınması Gereken Diğer Tamsayı Bölme Kitaplıkları

Elbette ABDKMath64x64 kütüphanesi, tamsayı bölme hatasını önlemenin yanı sıra doğruluğu artırmak için kullanılabilecek tek kütüphane değildir.


Fixidity , DSMath ve farklı sayı formatlarını kullanan BANKEX kütüphaneleri gibi birkaç örnekle birlikte birkaç tane daha vardır. Yukarıdaki örnekte kullanılan 64,64 bit sabit noktalı sayı formatından farklı sayı formatları. Bu nedenle, bu kitaplıkları keşfetmek yararlı görünse de, sayı biçimlerinin mevcut diğer kitaplıkların hiçbirinde çalışmayacağını lütfen unutmayın.