SORU
28 Mayıs 2009, PERŞEMBE


Nasıl tamsayılar bir bölümü her zaman yuvarlanır emin olabilir miyim?

Tamsayılar bir bölümü her zaman gerekirse yuvarlanır emin olmak istiyorum. Bundan daha iyi bir yolu var mı? Döküm bir sürü şey var. :-)

(int)Math.Ceiling((double)myInt1 / myInt2)

CEVAP
29 Mayıs 2009, Cuma


GÜNCELLEME: Bu soru the subject of my blog in January 2013 oldu. Harika soru için teşekkür ederiz!


Tamsayı aritmetik doğru almak zor. Fazlasıyla bugüne kadar "zeki", muhtemelen bir hata yaptın, bu iyi bir numara. bir deneyin şu an görüldüğü gibi, Ve bir kusur bulunduğunda, kod hatayı düzeltmek için değiştirmedüzeltme olup olmadığını dikkate almadan sonları başka bir şeyiyi bir problem çözme tekniği değildir. Şu ana kadar beş farklı yanlış tamsayı aritmetik çözümleri tamamen değil-özellikle zor sorun gönderildi bence geçirdik.

Doğru yaklaşım tamsayı aritmetik problemleri, yolu ihtimalini arttırır alma cevap hakkı ilk kez olduğu için yaklaşım sorunu dikkatlice çözmeye bir adım daha at, ve kullanımı iyi mühendislik prensipleri yapıyor.

Değiştirmek için çalışıyoruz ne için şartname okuyarak başla.Birleşik Devletleri: tamsayı için belirtimi

  1. Bölüm sonuç sıfıra doğru yuvarlar

  2. Sonuç iki işlenen ters belirtiler olduğunda iki işlenen aynı işareti ve sıfır veya negatif, sıfır veya pozitif

  3. Eğer sol işlenen temsil edilebilir en küçük int ve sağ işlenen ise -1, bir taşma oluşur. [...] uygulama tanımlı bir [ArithmeticException] atılır veya taşması sonucu değeri sol işlenen olarak bildirilmiyor olup olmadığını.

  4. Sağ işlenen değeri sıfırsa, bir Sistem.DivideByZeroException atılır.

İstediğimiz bölüm ama mermi sonucu hesaplayan tamsayı bölme bir fonksiyonudurhep yukarı doğrudeğilher zaman sıfıra doğru.

Yazma işlevi açısından önemli bir fırsattır.Bizim fonksiyonu int DivRoundUp(int dividend, int divisor) davranış mümkün olan her giriş için tanımlanmış olması gerekir. Bu tanımsız davranış derinden endişe verici, bu yüzden onu eleyelim. Örgütümüz bu belirtimi olan söyleriz:

  1. operasyon eğer bölen sıfır ise atar

  2. operasyon eğer temettü int ise atar.minval ve bölen -1

  3. eğer geri kalanı ise yok -- bölüm de -- sonra dönüş değeri ayrılmaz bir bölüm

  4. Aksi halde döneren küçüktamsayı olmasıdırdaha fazlabu bölüm daha, o, her zaman Yukarı yuvarlar.

Şimdi bir gelir yani bir şartname vartest edilebilir tasarım. Sanırım ekliyoruz ek bir tasarım kriteri bu sorun çözüldü sadece tamsayı aritmetik, yerine bilgi işlem bölüm olarak bir çift beri "çift" çözüm olmuştur açıkça reddetti, sorun bildirimi.

Biz hesaplamak için ne gerekir? Açıkça, sadece tamsayı aritmetik kalırken bizim spec karşılamak için, üç gerçekleri bilmek zorundayız. İlk olarak, tamsayı bölüm neydi? İkinci bölüm, kalan serbest oldu? Ve üçüncü olarak, eğer değil, tamsayı bölüm yukarı veya aşağı yuvarlama hesaplandı?

Bir şartname ve bir tasarım var artık kod yazmaya başlayabiliriz.

public static int DivRoundUp(int dividend, int divisor)
{
  if (divisor == 0 ) throw ...
  if (divisor == -1 && dividend == Int32.MinValue) throw ...
  int roundedTowardsZeroQuotient = dividend / divisor;
  bool dividedEvenly = (dividend % divisor) == 0;
  if (dividedEvenly) 
    return roundedTowardsZeroQuotient;

  // At this point we know that divisor was not zero 
  // (because we would have thrown) and we know that 
  // dividend was not zero (because there would have been no remainder)
  // Therefore both are non-zero.  Either they are of the same sign, 
  // or opposite signs. If they're of opposite sign then we rounded 
  // UP towards zero so we're done. If they're of the same sign then 
  // we rounded DOWN towards zero, so we need to add one.

  bool wasRoundedDown = ((divisor > 0) == (dividend > 0));
  if (wasRoundedDown) 
    return roundedTowardsZeroQuotient   1;
  else
    return roundedTowardsZeroQuotient;
}

Bu akıllıca mı? Hayır. Güzel mi? Hayır. Kısa mı? Hayır. Şartnameye göre doğru?Bende öyle düşünüyorum, ama tam olarak test etmedim.Oldukça iyi görünüyor.

Biz burada profesyoneliz; iyi mühendislik uygulamaları kullanın. Araştırma araçları, istenen davranışı belirtin, ilk hata durumlarda düşünün, vekodu bariz doğruluğu vurgulamak için yazıyorum.Ve bir hata bulduğunda, derin bir algoritma rasgele karşılaştırmaları yön değiştirme etrafında ve zaten çalışan eşyaları kırarlar başlamadan önce, başlamak için kusurlu olup olmadığını düşünün.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Floortile83

    Floortile83

    16 Ocak 2010
  • gsipek

    gsipek

    20 Temmuz 2007
  • Matt Davis

    Matt Davis

    4 ŞUBAT 2006