Neden 1.000.000.000'u 1000 * 1000 * 1000 olarak yazmalısınız?


142

Apple tarafından oluşturulan kodda şu satır var:

CMTimeMakeWithSeconds( newDurationSeconds, 1000*1000*1000 )

1,000,000,000Olarak ifade etmek için herhangi bir sebep var mı 1000*1000*1000?

Neden 1000^3bu konuda olmasın?


45
Kodun netliği ve okunabilirliği. C'ye ayırıcı olarak koyamazsınız veya bir sonraki en iyi şey, değeri bir çarpımdan hesaplamaktır. ^, C - exclusive OR içinde ilgisiz bir operatördür.
Iwillnotexist Idonotexist

54
Özellikle 2 * 60 * 60 gibi sürelerde kullanılır .. 2 saat için fark edilmesi kolaydır ..
Idali

53
Biri için 1.000.000.000 geçerli sözdizimi olduğundan şüpheleniyorum
paparazzo

15
Bu arada, modern programlama dilleri aynısını yazmak için alternatif yollara sahiptir, örneğin Swift'te 1_000_000_000. Bununla birlikte, zaman sabitleri ile bu daha zordur. Yazmak, yazmaktan 30 * 60(saniyede 30 dakika) daha okunabilir 1800. Aslında birimler yazmanıza izin verecek diller vardır, örneğin meterskendinizi kötü görevlere karşı korumanıza izin verir.
Sulthan

29
^bir XOR, bir üs veya güç operatörü değil.
3Dave

Yanıtlar:


200

Sabitleri çarpımsal bir şekilde bildirmenin bir nedeni, çalışma zamanı performansı etkilenmezken okunabilirliği artırmaktır. Ayrıca, yazarın sayı hakkında çarpımsal bir şekilde düşündüğünü belirtmek.

Bunu düşün:

double memoryBytes = 1024 * 1024 * 1024;

Açıkça daha iyidir:

double memoryBytes = 1073741824;

çünkü ikincisi ilk bakışta 1024'ün üçüncü gücüne bakmıyor.

Amin Negm-Awad'ın belirttiği gibi, ^operatör ikiliktir XOR. Birçok dilde yerleşik, derleme zamanı üs alma işleci yok, dolayısıyla çarpma.


13
Ve bir üs alma işlecine sahip dillerde, mutlaka '^' değildir. Örneğin Fortran'da bu '**'.
jamesqf

4
Ayrıca, aşağıdaki cevapta verilen önemli uyarıya işaret eden bir bağlantıyı da @chux: stackoverflow.com/a/40637622/1841533 adresinden (özellikle bu 'elden' çok hassas olan "c" olarak etiketlenmiş olarak) eklemelisiniz. yan işlemin tüm terimlerin daha küçük bir türle sınırlı olduğu görülür ve bu nedenle çarpma 'sorunu aşabilir). securecoding.cert.org/confluence/display/c/… genel durumdakilerden kaçınmaya yardımcı olabilir mi?
Olivier Dulac

4
Ayrıca hesaplamanın derleme zamanında yapıldığını da not etmeliyiz. C Standardı, uygulamanın dilin çeşitli özellikleri için derleme zamanında sabit ifadeleri hesaplayabilmesini gerektirir ve bu örnekte olduğu gibi sabit bir ifade kullanıldığında bunun doğru olduğunu kabul edebiliriz.
ouah

13
Bellek miktarını çift olarak mı saklıyorsunuz? Bu potansiyel bir hata kaynağı gibi görünüyor.
JAB

7
@supercat Bunun farkındayım, ancak double kullanarak, örneğin, bellek aralığının bir kısmını istediğiniz x, subrange'in boyutunu elde etmek için bölündüğünüz bir durum olabilir ... ve aniden kesirliğiniz var telafi etmek için ek mantık gerektirebilecek bayt.
JAB

73

Neden olmasın 1000^3?

1000^31003 sonucudur. ^Bit-XOR operatörüdür.

Q'nun kendisi ile ilgilenmese bile, bir açıklama ekliyorum. x^yyok değil her zaman için değerlendirmek x+yo sorunu olanın örnekte olduğu gibi. Her parçayı xor yapmanız gerekiyor. Örnek olması durumunda:

1111101000 (1000₁₀)
0000000011 (3₁₀)
1111101011 (1003₁₀)

Fakat

1111101001 (1001₁₀)
0000000011 (3₁₀)
1111101010 (1002₁₀)

3
efendim, 1003 ^ 3'ün 1003 olduğu net değil. Google ve Mac Hesap Makinesi 1000 ^ 3 = 1.000.000.000 gösteriyor. açıklayabilir misin?
Mahesh

57
^C / C ++ / Amaç-C gibi hesap olarak genellikle aracı, x-için-y güç operatör araçları XOR.
Tamás Zahola

5
Bah, 1000 ve 3 bitleri çakışmaz. Bu çok yanlış görünüyor .
Yakk - Adam Nevraumont

19
Bitler çakışıyor. Ama 1 değil. : -]
Amin Negm-Awad

6
@Yakk: gerçekten çok yanlış görünüyor! ... Umarım birçok insan "A ^ B" nin her zaman A + B verdiğini düşünmez (ama bazılarının korkmasından korkarım ...)
Olivier Dulac

71

Nedeni vardır değil kullanmak 1000 * 1000 * 1000.

16-bit ile int, 1000 * 1000taşıyor. Böylece kullanmak 1000 * 1000 * 1000taşınabilirliği azaltır.

32-bit ile int, aşağıdaki ilk kod satırı taşar.

long long Duration = 1000 * 1000 * 1000 * 1000;  // overflow
long long Duration = 1000000000000;  // no overflow, hard to read

Olası satış değerinin, okunabilirlik, taşınabilirlik ve doğruluk için hedef türüyle eşleşmesini önerin .

double Duration = 1000.0 * 1000 * 1000;
long long Duration = 1000LL * 1000 * 1000 * 1000;

Ayrıca e, tam olarak a olarak temsil edilebilen değerler için gösterimi basit bir şekilde kullanabilir double. Elbette bu double, tam sayı değerini tam olarak temsil edip edemeyeceğini bilmeye yol açar - 1e9'dan büyük değerlerle ilgili bir şey. (Bkz. DBL_EPSILONVe DBL_DIG).

long Duration = 1000000000;
// vs.
long Duration = 1e9;

5
Çok önemli bir açıklama! securecoding.cert.org/confluence/display/c/… birçok durumda yardımcı olabilir mi?
Olivier Dulac

2
A doubletam olarak 2 ^ 53 ≈ 9e15'e kadar olan tam sayıları temsil edebilir.
Edgar Bonet

3
@EdgarBonet Binary64'ün 9e15'e kadar tam sayıyı temsil edebileceği doğrudur. Ancak C double, çok yaygın kullanılmasına rağmen binary64 kullanımını belirtmez . C spesifikasyonuna göre, 1e9'a kadar olan değerler tam olarak temsil edilebilir. Spesifikasyonu kodlamak veya ortak uygulamaya güvenmek isteyip istemediğinize bağlıdır.
chux - Monica'yı

4
Hem @Patrick 1000ve 1000000000000olan sabitler tamsayıdır . Her biri bağımsız olarak int, longveya arasından seçilir long long. Derleyici, tamsayı sabitinin sığdığı ilk 3 tipi kullanır . 1000 * 1000 * 1000 * 1000ile yapılır inther şekilde matematik 1000bir in int. Ürün 32 bit ile taşar int. 1000000000000 kesinlikle long long(veya muhtemelen daha dar) olarak temsil edilebilir - taşma olmaz. Hedefin türü, long long Duration"=" eksikliğinin bu "sağ tarafını etkilemez.
chux - Monica'yı

2
Çarpma işlemine daha geniş tipin ilk yerleştirilmesi önemlidir. 16-bit ile int, long x = 1000 * 1000 * 1000L;ise, taşacak durumdaki long x = 1000L * 1000 * 1000;olmaz.
eski nihilo

51

Okunabilirlik için.

Sıfırlar ( 1 000 000 000veya 1,000,000,000) arasına virgül ve boşluk yerleştirmek bir sözdizimi hatası oluşturur ve 1000000000koda sahip olmak, tam olarak kaç sıfır olduğunu görmeyi zorlaştırır.

1000*1000*100010 ^ 9 olduğu anlaşılıyor, çünkü gözlerimiz parçaları daha kolay işleyebiliyor. Ayrıca, çalışma zamanı maliyeti yoktur, çünkü derleyici bunu sabitle değiştirecektir 1000000000.


5
Bilginize, son zamanlarda öğrendiğim bir basamak ayırıcı kavramı var. Java bir süredir sahipti ve C # 7.0 bunu alabilir. Keşke tüm diller bu şekerleme özelliğine sahip olsaydı. :)
iheartcsharp

1
Bağlama göre 1,000,000,000sözdizimi hatası üretmez, başka bir şey ifade eder. ÖrneğinCMTimeMakeWithSeconds( newDurationSeconds, 1,000,000,000 )
Ross Ridge

2
@ JMS10 C #, VS15 önizleme sürümünü yüklerseniz zaten var, kullanıcı olarak yazılabilir1_000_000_000
user1306322

2
Python da _ayırıcı oluyor :)
Wayne Werner

2
Ve C ++ yakın zamanda 'C ++ 14'te ayırıcıyı aldı , böylece kullanabilirsiniz 1'000'000'000. ( 1,000,000,000Virgül operatörü veya 4 farklı parametre olarak yanlış yorumlanabileceğinden ve _1_000_000_000geçerli (ancak muhtemelen kötü) bir değişken adı olduğu için seçildi .)
Justin Time - Monica'yı

27

Okunabilirlik için. Karşılaştırma için, Java, _okunabilirliği artırmak için sayıları desteklemektedir (ilk olarak Stephen Colebourne tarafından Derek Foster'ın ÖNERİSİ: Project Coin / JSR 334 için İkili Değişmezlere cevap olarak önerilmiştir ). Biri 1_000_000_000buraya yazar.

Kabaca kronolojik sırayla, en eski destekten en yenisine:

Dillerin desteklemeleri gerektiğini fark etmeleri için nispeten yeni bir özellik (ve sonra Perl var). Chux @ 'un mükemmel cevabında 1000*1000...olduğu gibi, kısmi bir çözümdür, ancak nihai sonuç büyük bir tür olsa bile, programlayıcıyı çarpımdan taşan hatalara kadar açar.


Birçok modern programlama dili aynıdır, örneğin Swift. Herşey aynı.
Sulthan

AFAIK, bu Perl'den geliyor. PL / M $ aynı amaçla kullanılır, örn: 0100 $ 0010B
ninjalj

1
Yine de oldukça yenidir. Java özelliği belki 5 yaşındadır. Bu sözdizimini destekleyen diğer birçok dil oldukça yenidir - Swift'in kendisi sadece birkaç yaşındadır. Python, 3.6'da henüz desteklenmeyen bir destek ekliyor.
johncip

2
Ada, 33 yıldır tam sayı değişmezlerinde alt çizgileri destekliyor.
Peter - Monica'yı

1
@djechlin: Kabaca kronolojik sırayla daha fazla bilgi ekleme özgürlüğünü aldım. Daha önce yanılmıştım, Project Coin iş parçacığına göre, Stephen Colebourne muhtemelen Fandom ve / veya Ruby'den tamsayı değişmezlerde alt çizgi fikrini aldı. Ruby muhtemelen Perl'den ve Perl Ada'dan aldı.
ninjalj

7

1,000,000,000Formu okumak ve formla bazı ilişkilendirmeler almak daha kolay olabilir.

Teknik açıdan, doğrudan sayı veya çarpma arasında bir fark olmadığını düşünüyorum. Derleyici yine de sabit milyar sayısı üretecektir.

Eğer objektif-c hakkında konuşursanız, o 1000^3zaman işe yaramaz çünkü pow için böyle bir sözdizimi yoktur (xor). Bunun yerine pow()işlev kullanılabilir. Ancak bu durumda, optimal olmayacak, derleyici tarafından üretilen bir sabit değil, bir çalışma zamanı işlevi çağrısı olacaktır.


3

Nedenleri göstermek için aşağıdaki test programını göz önünde bulundurun:

$ cat comma-expr.c && gcc -o comma-expr comma-expr.c && ./comma-expr
#include <stdio.h>

#define BILLION1 (1,000,000,000)
#define BILLION2 (1000^3)

int main()
{
        printf("%d, %d\n", BILLION1, BILLION2);
}
0, 1003
$

1
@pjvandehaar Wikipedia makalelerini okuyarak dil öğrenmenizi tavsiye etmem.
Peter - Monica'yı

0

Ondalık sayılar için C'de benzer bir etki elde etmenin bir başka yolu, gerçek bir kayan nokta gösterimi kullanmaktır - bir çift, herhangi bir hassasiyet kaybı olmadan istediğiniz sayıyı temsil edebildiği sürece.

IEEE 754 64 bit çift, negatif olmayan herhangi bir <= 2 ^ 53 tamsayısını sorunsuz olarak temsil edebilir. Tipik olarak, uzun çift (80 veya 128 bit) bundan daha da ileri gidebilir. Dönüşümler derleme zamanında yapılacaktır, bu nedenle çalışma zamanı yükü yoktur ve beklenmedik bir hassasiyet kaybı varsa ve iyi bir derleyiciniz varsa büyük olasılıkla uyarılar alırsınız.

long lots_of_secs = 1e9;
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.