Bu kodu yazıyordum:
public static void main(String[] args) {
double g = 1 / 3;
System.out.printf("%.2f", g);
}
Sonuç 0'dır. Bu neden oluyor ve bu sorunu nasıl çözebilirim?
Yanıtlar:
İki işlenen (1 ve 3) tam sayıdır, bu nedenle tam sayı aritmetik (burada bölme) kullanılır. Sonuç değişkeninin çift olarak bildirilmesi, bölmeden sonra örtük bir dönüşümün gerçekleşmesine neden olur .
Elbette tamsayı bölme, sıfıra yuvarlanmış bölmenin gerçek sonucunu verir. Sonucu0.333...
burada 0'a yuvarlanır. (İşlemcinin aslında herhangi bir yuvarlama yapmadığını unutmayın, ancak yine de bu şekilde düşünebilirsiniz.)
Ayrıca, her iki işlenen (sayı) yüzer olarak verildiğinde; 3.0 ve 1.0 veya hatta sadece ilk , daha sonra kayan nokta aritmetiği kullanılır, size verir 0.333...
.
DOWN
sıfıra doğru. Yuvarlama FLOOR
, negatif sonsuza doğrudur.
1/3
her iki taraf da tam sayı olduğundan tamsayı bölme kullanır.
Bunlardan İhtiyacınız en az biri olmak float
veyadouble
.
Sorunuz gibi kaynak koddaki değerleri giriyorsanız şunları yapabilirsiniz 1.0/3
; 1.0
Bir iki katı.
Eğer başka bir yerden değerleri alırsanız kullanabilirsiniz (double)
açmak için int
bir içine double
.
int x = ...;
int y = ...;
double value = ((double) x) / y;
kullanmalısın
double g=1.0/3;
veya
double g=1/3.0;
Tamsayı bölümü tamsayı döndürür.
Çünkü tamsayı bölme yapıyorsun.
@Noldorin'in dediği gibi, her iki operatör de tamsayı ise, tamsayı bölme kullanılır.
Sonuç 0.33333333 bir tamsayı olarak gösterilemez, bu nedenle sonuca yalnızca tamsayı kısmı (0) atanır.
Operatörlerden herhangi biri bir double
/ ise float
, kayan nokta aritmetiği yer alacaktır. Ancak bunu yaparsanız aynı sorunu yaşarsınız:
int n = 1.0 / 3.0;
Çünkü 1 ve 3'ü tam sayı olarak ele aldığı için sonucu 0'a yuvarlayarak bir tamsayı olur.
Aradığınız sonucu elde etmek için, java'ya açıkça sayıların iki katı olduğunu söyleyin:
double g = 1.0/3.0;
JAVA'daki dönüştürme oldukça basittir ancak biraz anlayış gerektirir. Tamsayı işlemleri için JLS'de açıklandığı gibi :
Kaydırma operatörü dışındaki bir tamsayı operatörünün en az bir uzun işlenen tipine sahip olması durumunda, işlem 64 bitlik hassasiyet kullanılarak gerçekleştirilir ve sayısal operatörün sonucu uzun tiptedir. Diğer işlenen uzun değilse, önce sayısal yükseltme (§5.6) ile long yazmak için genişletilir (§5.1.5).
Ve bir örnek her zaman JLS'yi çevirmenin en iyi yoludur;)
int + long -> long
int(1) + long(2) + int(3) -> long(1+2) + long(3)
Aksi takdirde, işlem 32 bitlik kesinlik kullanılarak gerçekleştirilir ve sayısal operatörün sonucu int türündedir. İşlenenlerden herhangi biri bir int değilse, önce sayısal yükseltmeyle int türüne genişletilir.
short + int -> int + int -> int
Eclipse kullanan küçük bir örnek, iki " short
nin eklenmesinin bile o kadar kolay olmayacağını göstermek için:
short s = 1;
s = s + s; <- Compiling error
//possible loss of precision
// required: short
// found: int
Bu, olası bir hassasiyet kaybına sahip bir döküm gerektirecektir.
Aynısı kayan nokta operatörleri için de geçerlidir
Bir sayısal operatörün işlenenlerinden en az biri double türünde ise, işlem 64-bit kayan noktalı aritmetik kullanılarak gerçekleştirilir ve sayısal operatörün sonucu double türünde bir değerdir. Diğer işlenen bir double değilse, önce sayısal yükseltmeyle double (§5.6) yazmak için genişletilir (§5.1.5).
Böylece terfi şamandırada iki katına çıkarılır.
Hem tam sayı hem de kayan değerin karışımı, belirtildiği gibi kayan değerlerle sonuçlanır
Bir ikili operatörün işlenenlerinden en az biri kayan nokta tipindeyse, diğeri integral olsa bile işlem bir kayan nokta işlemidir.
Bu, ikili operatörler için doğrudur ancak "Atama Operatörleri" için geçerli değildir. +=
Bunu kanıtlamak için basit bir çalışma örneği yeterlidir
int i = 1;
i += 1.5f;
Nedeni, burada yapılan örtük bir döküm var, bu şu şekilde yürütülecek
i = (int) i + 1.5f
i = (int) 2.5f
i = 2
1 ve 3 Contants tamsayı vardır ve Java bir tamsayı bölme yapar, böylece size yazmak zorunda çift sabitleri yazmak istiyorsanız hangi ettiği sonuç 0'dır 1.0
ve 3.0
.
En kolay çözüm sadece bunu yapmaktır
double g = ((double) 1 / 3);
1.0 / 3.0 girmediğiniz için bunun yaptığı şey, Java'nın bunun Tamsayı bölümü olduğunu varsaydığından ve dönüşümü daraltmak anlamına gelse bile bunu yapacağından, bunu manuel olarak çift veri türüne dönüştürmenize izin vermektir. Bu, döküm operatörü olarak adlandırılan şeydir.
Bunu ben yaptım.
double g = 1.0/3.0;
System.out.printf("%gf", g);
Çift hesaplama yaparken .0 kullanın, aksi takdirde Java, Tamsayı kullandığınızı varsayacaktır. Bir Hesaplama herhangi bir miktarda çift değer kullanırsa, çıktı bir çift değer olacaktır. Tüm Tamsayılar ise, çıktı bir Tamsayı olacaktır.
(1/3), Tamsayı bölümü anlamına gelir, bu nedenle bu bölümden ondalık değer alamazsınız. Bu sorunu çözmek için şunları kullanın:
public static void main(String[] args) {
double g = 1.0 / 3;
System.out.printf("%.2f", g);
}
public static void main(String[] args) {
double g = 1 / 3;
System.out.printf("%.2f", g);
}
Hem 1 hem de 3 tam sayı olduğundan, sonuç yuvarlanmamıştır, ancak kesilmiştir. Yani kesirleri yok sayarsınız ve sadece bütünleri alırsınız.
Bundan kaçınmak için 1 veya 3 numaralarınızdan en az birini 1.0 ve / veya 3.0 ondalık formunda bulundurun.
Şunu deneyin:
public static void main(String[] args) {
double a = 1.0;
double b = 3.0;
double g = a / b;
System.out.printf(""+ g);
}
"Double g = 1.0 / 3.0;" yapın yerine.
Diğer pek çok kişi de asıl meseleyi belirtmekte başarısız oldu:
Yalnızca tam sayılar üzerinde yapılan bir işlem, işlemin sonucunu bir tam sayıya çevirir.
Bu ille nokta sonuçlarını yüzen bu demek ki, olabilir bir tamsayı olarak gösterilecektir, kesilecek (ondalık kısmı kapalı sarkık).
Döküm nedir sormak (tiplemeleri / tip dönüşümü)?
Dilin uygulanmasına göre değişir, ancak Wikipedia oldukça kapsamlı bir görüşe sahip ve zorlama hakkında konuşuyor sorunuzu yanıtlarken çok önemli bir bilgi olan .
1/2
Hedef dilde (java) olduğu gibi , tamsayı bir tamsayı bölünmesine dahil olan Tip Döküm veya Tip Dönüştürme yoktur . Sadece bir tamsayı bölümü çağırırsınız, bu da bir tamsayı sonucuyla sonuçlanır. Tip Döküm sırf yukarı-dönüşüm olduğunu int
bir etmek double
atama sırasında.
0.5
. Basitçe, Java'da, 1/2
sıfır tamsayı ile sonuçlanan bir tamsayı bölümüdür. Bir double'a sıfır atayabilirsiniz, bu bir 0.0
double da olsa yine de sıfır olacaktır .
int i = .99999999
int'i 0'a ayarlar. Daha spesifik olarak, tamsayı kısmını alır ve gerisini atar.