Java / C ++ işletim sistemlerinde neden güç operatörü yok?


23

**Python'da böyle bir operatör varken, Java ve C ++ 'ın da neden sahip olmadığını merak ediyordum.

C ++ 'da tanımladığınız sınıflar için operatör aşırı yüklemesi ile bir tane yapmak kolaydır (ve Java ile de böyle bir şey mümkün olduğuna inanıyorum), ancak int, double ve benzeri gibi ilkel türlerden bahsederken, kütüphane kullanmanız gerekir. gibi işlev görür Math.power(ve genellikle ikisini de ikiye katlarlar).

Öyleyse - neden ilkel türler için böyle bir operatör tanımlamıyorsunuz?


8
C ++ 'ta kendi operatörlerimizi oluşturamıyoruz. Sadece mevcut operatörleri aşırı yükleyebilirsiniz.

1
@Mahesh, böylece kendi Number sınıfımı oluşturabilirim ve bir güç olması için aşırı yük operatörüm olabilir. Bu gerçekten önemli değil.

22
@RanZilber: İşleç önceliği, üstelleştirme önceliği ile ^eşleşmediğinden önemli. İfadeyi düşünün a + b ^ c. Matematikte, üstel ilk önce ( b ^ c) gerçekleştirilir , ardından elde edilen güç eklenir a. C ++ 'da önce ekleme ( a + b) ^yapılır, ardından operatör ile gerçekleştirilir c. Yani ^operatörü üsteleme yapmak için uygulasanız bile, öncelik herkesi şaşırtacaktır.
silico'da

2
@RamZilber - ^C ++ 'da bir XOR'dir . Aşırı yüklenmiş bir operatörün, ilkel bir veri tipinin bunu kullanarak yaptıklarından hiçbir şey yapmaması önerilir.

4
@RanZilber: Çünkü üstelleştirme demek istediğin bu operatörlerden herhangi birini kullanmak hiç de sezgisel değil. ++Operatörü veya operatörü aşırı yükleyen herhangi bir C ++ programcısının yeterliliğini ciddi bir şekilde sorgulayacağım !. ark. üstel demek. Ama yine de yapamazsınız, çünkü konuştuğunuz operatörler yalnızca bir argümanı kabul eder; üstelleştirme iki argüman gerektirir.
silico'da

Yanıtlar:


32

Genel olarak konuşursak, C'deki ilkel operatörler (ve C ++ uzantısına göre) kabaca tek bir komutta basit donanımlarla uygulanabilecek şekilde tasarlanmıştır. Üstellik gibi bir şey genellikle yazılım desteği gerektirir; bu yüzden varsayılan olarak orada değil.

Ayrıca, dilin standart kütüphanesi tarafından sağlanır std::pow.

Son olarak, bunu tamsayı veri türleri için yapmak pek mantıklı olmaz, çünkü üstelleştirme için küçük değerler bile int için gerekli olan aralığı, 65,535'e kadar yükseltir. Elbette, bunu çiftler ve yüzmek için yapabilirsin, ama içindekiler için değil, ama dili neden nadiren kullanılan bir özellik için tutarsız kılıyor?


4
Bunların çoğuna katılıyorum, ancak modül operatörünün kayan nokta tiplerinde kullanılamaması, ilkel veri tipleri için tutarsız, ancak muhtemelen benim tahmin ettiğim herhangi bir donanım için tek bir talimat olmayacak.

@Sion: En azından x86'da, modül tek bir komuttur. ( DIVbölünme ve modulü yapar) Olsa da beni tutarlılık noktasında tuttun.
Billy ONeal

@Billy ONeal: Tek komutta kayan nokta modülü? Kendimi tanımak için geç saatlerde mecliste dolanmadım. Bu durumda, modül operatörü kayan nokta tiplerine uygulanabilir hale getirilmelidir.

3
@DonalFellows: FORTRAN, üssü operatörüne bignum desteğine benzer bir şey yapmadan çok önce vardı.
supercat,

1
@ DonalFellows: Bir güç operatörü, tam sayılarla, yüzdürme sayıları kadar faydalı değildir, ancak küçük güçler için (özellikle kareler) kesinlikle kullanımlarına sahip olabilir. Şahsen ben operatörlerin harflerden çıkma yaklaşımını seviyorum (Pascal'ın yaptığı divveya FORTRAN'ın olduğu gibi .EQ.); dil boşluğu kurallarına bağlı olarak, isteğe bağlı sayıda operatöre, sözcük ayırmalarını gerektirmeden keyfi bir şekilde sahip olmak mümkün olabilir.
supercat

41

Bu soru C ++ için cevaplıdır: Stroustrup, "C ++ 'ın Tasarımı ve Evrimi" bu konuyu 11.6.1, pp. 247-250.

Yeni bir operatör eklemek için genel itirazlar vardı. Zaten aşırı karmaşık öncelik tablosuna eklerdi. Çalışma grubunun üyeleri bir işleve sahip olmanın sadece küçük bir kolaylık sağlayacağını düşünüyorlardı ve bazen kendi işlevlerini yerine koymak istiyorlardı.

Bir operatör için iyi bir aday yoktu. ^özel veya ve olduğu ^^çünkü arasındaki ilişkinin davet karışıklık &ve |ve &&ve ||. Mevcut bir değerin !üstelleştirilmesi için yazma eğilimi olacağından !=ve bu zaten alınmışsa uygun değildi. En iyisi *^, görünüşe göre kimsenin gerçekten hoşlanmadığı bir şey olabilirdi.

Stroustrup kabul **yine ama zaten C bir anlamı vardır: a**pbir akere ne olursa olsun ppuan ve char ** c;beyan cetmek göstericisinin göstericisi olarak char. **"İşaretçinin işaretçiye bildirimi", "bir sonraki şeyin işaret ettiği zaman" (işaretçi ise) veya "üstelleştirme" (bir sayı tarafından takip edilirse), öncelikli sorunlara neden olan bir simge olarak tanıtmak . p bir a/b**psayıymış gibi ayrıştırmak zorunda kalacaktı a/(b**p)ancak (a/b) * *pp bir işaretçi olsaydı, bu ayrıştırıcıda çözülmek zorunda kalacaktı.

Başka bir deyişle, mümkün olurdu, ancak öncelik tablosu ve ayrıştırıcıyı karmaşıklaştırırdı ve ikisi de zaten çok karmaşıktı.

Java ile ilgili hikayeyi bilmiyorum; Yapabileceğim tek şey spekülasyon olurdu. C'ye geldiği yerde, tüm C operatörleri kısmen derleyiciyi basitleştirmek ve kısmen basit operatörlerde zaman alan işlevsellikten saklanmaktan kaçınmak için kolayca montaj koduna çevrilir ( operator+()diğerleri ve diğerlerinin büyük karmaşıklık ve performans isabetlerini gizleyebilmesi bir idi) C ++ ile ilgili erken şikayetlerden.


2
Güzel cevap Sanırım Java bu konuda C basitleştirmeye çalıştı, bu yüzden kimse yeni bir operatör eklemek istemiyordu. Kimse bana sormadı üzücü, kesinlikle isterdi *^. : D
maaartinus

1
C metin biçimlendirme yapmak için oluşturulmuştur. Fortran matematik yapmak için inşa edilmiş ve 20 yıl önce karmaşık, güç ve matris matematik vardı.
Martin Beckett

@ Martin Beckett: C'nin metin biçimlendirme için oluşturulduğuna dair kanıt bulabilir misiniz? Bana bunun için oldukça sakar bir dil gibi geliyor ve C'nin kökeni hakkında okuduklarım, öncelikle Unix için sistem programlaması için tasarlandığını söylüyor.
David Thornley

@DavidThornley - Unix'i yazmak için tasarlandı, ancak tüm Unix kullanımlarının tümü metin biçimlendirmiş gibi görünüyor ve bunun için geniş bir dize ve i / o kitaplığı var.
Martin Beckett

6
+1: Varolan anlam a**p, katil. (Bu soruna geçici bir çözüm bulmak için hack… Brr!)
Donal Fellows

13

Ben şüpheli Eğer tanıtmak her operatör dilin karmaşıklığını artırır çünkü bu kadar. Giriş engeli bu nedenle çok yüksektir. Kendimi üstelleştirmeyi çok nadiren kullanırken buluyorum - ve bunu yapmak için bir yöntem çağrısı kullanmaktan çok mutluyum.



3
Bunu kullanırdım x**2ve x**3nadiren kullanmazdım . Ve derleyicinin basit vakalar için bildiği ve optimize ettiği sihirli bir güç uygulaması iyi olurdu.
CodesInChaos

2
@CodeInChaos: Ancak x * xve x * x * xmeydanda ve küp için kötü yerini tutmaz.
David Thornley

5
@David, x*xeğer x bir ifade ise, yazamazsınız . En iyi durumda, kod bozulmaz hale gelir ve en kötüsünde yavaş veya hatta yanlış. Böylece kendi Kare ve Küp işlevlerinizi tanımlamanız gerekir. Ve o zaman bile kod, operatör olarak ** kullanmaktan daha çirkin olurdu.
CodesInChaos

1
@David Parantez koymam gerekiyor evet, ancak ifadeyi birkaç kez tekrar etmem ve kaynak kodunu kesmem gerekmiyor. Okunabilirliği çok azaltır. Ve genel alt-ifadenin kaldırılması, sadece derleyicinin ifadenin yan etkilerden arındırılmış olduğunu garanti etmesi durumunda mümkündür. Ve en azından .net jitter bu konuda akıllı değil.
CodesInChaos

11

Java dili ve çekirdek kütüphane tasarımcıları çoğu matematik işlemlerini Math sınıfına devretmeye karar verdi . Math.pow () işlevine bakınız .

Niye ya? Bit-bit hassasiyetinde performansa öncelik verme esnekliği. Yerleşik matematik operatörlerinin davranışlarının platformdan platforma kadar değişebileceğini söylemek, dilin belirttiğine aykırı davranırken, Matematik dersi özellikle davranışın performans için hassasiyetten fedakarlık ettiğini belirtir.

StrictMath sınıfının sayısal yöntemlerinden bazılarının aksine , Math sınıfının eşdeğer işlevlerinin tüm uygulamaları, bit-bit aynı sonuçları döndürecek şekilde tanımlanmaz. Bu gevşeme, katı tekrarlanabilirliğin gerekli olmadığı durumlarda daha iyi performans gösteren uygulamalara izin verir.


6

Üreme, baştan beri Fortran'ın bir parçasıydı, çünkü tamamen bilimsel programlamaya yönelikti. Mühendisler ve fizikçiler simülasyonlarda sıkça kullanırlar, çünkü güç yasası ilişkileri fizikte ortaktır.

Python da bilimsel hesaplamada güçlü bir varlığa sahiptir (örneğin NumPy ve SciPy). Üstelik üstelik işletmecisi ile birlikte, bilimsel programlamayı da hedeflediğini öne sürüyor.

C, Java ve C # sistem programlamasında köklere sahiptir. Belki de üstelleştirmeyi, desteklenen operatör grubunun dışında tutan bir etki.

Sadece bir teori.


4

C sadece ALU'ya uygun ortak aritmetik işlemler için tanımlanmış operatörler. Asıl amacı, derleme koduna okunabilir bir arayüz oluşturmaktı.

C ++ herhangi bir operatör davranışını değiştirmedi çünkü C ile yazılmış tüm kod tabanlarının uyumlu olmasını istedi.

Java da aynı şeyi yaptı çünkü mevcut C ++ programcılarını korkutmak istemedi.


C oluşturulduğunda, çarpma ve bölme nadiren donanımdan yoksundu ve yazılımda uygulanmalıydı. Yine de C çarpma ve bölme operatörlerine sahiptir.
siride

@siride: Bildiğim kadarıyla, PDP-7, Unix'i ilk kullanan bilgisayardı, EAE'sinde donanım çarpımı ve bölmesi vardı. Lütfen bakınız: bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf
Tugrul Ates

1

Çünkü güç için anlamlı olan her operatör zaten kullanılıyor. ^, XOR'dir ve **, bir işaretçiyi bir işaretçiye işaret eder. Bunun yerine, aynı şeyi yapan bir işleve sahipler. (pow () gibi)


@RTS - Bir dil geliştiricisi geliştiriciden, verimlilikten daha fazlasını sağlamaya çalışıyor mu?

Bir programlama dilinin iyi bir geliştiricisi her ikisine de bakar. Java hakkında hiçbir şey söyleyemem. Ancak c ++ 'ta pow () işlevi derleme zamanında hesaplanır. Ve normal operatörler kadar verimlidir.

@RTS: pow()sizin için sürekli katlama yapabilen bir derleyici var sürece işlev, çalışma zamanında onun hesaplama gerçekleştirir pow()hangi ederim şüphe. (Bazı derleyiciler hesaplamayı yapmak için size işlemci intrintiği kullanma seçeneği
sunarlar

@ Silico: Nihai değeri hesapladığı anlamına gelmez, derleyicilerin işlev çağrısını en iyi duruma getireceği anlamına geliyordu, bu yüzden sadece ham denkleminiz var.

2
@josefx: Tabii ki iyi bir sebep. Tek *, dolaylı ya da çarpma için kullanılmış olsun, sözlüksel bir simgedir. Bir **anlam üstü ifadesi ya bir ya da iki sözcük belirteçleri olabilir ve gerçekten de dilekçenizin sembolize etmek için sembol masasına vurmasını istemezsiniz.
David Thornley

0

Aslında, aritmetik operatörler sadece fonksiyonların kısayollarıdır. (Neredeyse) Onlarla yaptığınız her şey bir işlevle yapılabilir. Örnek:

c = a + b;
// equals
c.set(a.add(b));
// or as free functions
set(c, add(a,b));

Bu sadece daha ayrıntılı, bu yüzden 'gücünü' gerçekleştirmek için işlevler kullanarak yanlış bir şey göremiyorum.


-1

Toplama / çıkarma / olumsuzlama ve çarpma / bölme temel matematik operatörleridir. Eğer gücü bir operatör yapacak olsaydın, nerede dururdun? Karekök operatörü? N-root operatörü? Logaritma operatörü?

Yaratıcıları için konuşamam, ancak bu tür operatörlerin dilde konuşmasının ortogonal olmadığını ve saçma olacağını düşünüyorum diyebilirim. Klavyede kalan alfa-sayısal / beyaz boşluk karakterlerinin sayısı oldukça sınırlıdır. Olduğu gibi, C ++ 'da bir modül işleci olması garip.


+1 - modBir operatör olarak sahip olmanın neden garip olduğunu anlamıyorum . Bu genellikle tek bir talimattır. Tam sayılarda ilkel bir işlem. Bilgisayar biliminde her yerde kullanılır. (Sınırsız arabellek gibi şeyler modyapmak kıyameti
bozulmaz

@Billy ONeal: Tamsayı tipleri ve kayan nokta tipleri ile kullanılamaması arasındaki tutarsızlık nedeniyle garip. Kesinlikle faydalı olsa da, kaldırmayı hayal etmem. Sadece ilginç olan her şey.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.