dc (bilgisayar programı) - dc (computer program)
| Orijinal yazar(lar) |
Robert Morris ( AT&T Bell Laboratuvarları ) |
|---|---|
| Geliştirici(ler) | Çeşitli açık kaynaklı ve ticari geliştiriciler |
| Yazılmış | B |
| İşletim sistemi | Unix , Unix benzeri , Plan 9 |
| platformu | Çapraz platform |
| Tip | Emretmek |
dc ( masa hesap makinesi ), keyfi hassasiyette aritmetiği destekleyen çapraz platformlu bir ters cilalı hesap makinesidir . Tarafından yazıldı Robert Morris iken Bell Labs , o eski biridir Unix bile buluşu önceki, kamu hizmetleri C programlama dilinde . Bu vintagein diğer yardımcı programları gibi, güçlü bir dizi özelliğe ama özlü sözdizimine sahiptir. Geleneksel olarak, bc hesaplayıcı programı ( infix notasyonu ile ) dc'nin üzerine uygulandı.
Bu makale, dile genel bir bakış açısı kazandırmak amacıyla bazı örnekler sunmaktadır; komutların ve sözdiziminin tam listesi için, kişinin özel uygulaması için man sayfasına bakılmalıdır .
Tarih
dc, hayatta kalan en eski Unix dil programıdır. Evi Bell Labs bir PDP-11 aldığında , B ile yazılmış dc , bir montajcıdan önce bile yeni bilgisayarda çalışan ilk dildi. Ken Thompson , dc'nin makinede yazılan ilk program olduğunu belirtti.
Temel işlemler
DC'de dört ve beşi çarpmak için ( boşluğun çoğunun isteğe bağlı olduğunu unutmayın ):
$ cat << EOF > cal.txt
4 5 *
p
EOF
$ dc cal.txt
20
$
Sonucu komutlarla da alabilirsiniz:
$ echo "4 5 * p" | dc
veya
$ dc -
4 5*pq
20
$ dc
4 5 *
p
20
q
$ dc -e '4 5 * p'
Bu, "dördü ve beşi yığının üzerine itin, ardından çarpma operatörüyle yığından iki öğe çıkarın, bunları çarpın ve sonucu yığına geri itin" anlamına gelir. Daha sonra pkomut, yığındaki en üst öğeyi incelemek (ekrana yazdırmak) için kullanılır. qKomut dc çağrılan örneğini çıkar. Bazı operatörler gerekmese bile sayıların birbirinden boşluk bırakılması gerektiğini unutmayın.
Aritmetik hassas komutu ile değiştirilir kkesirli basamak sayısını (aşağıdaki basamak sayısını ayarlar alanına aritmetik işlemler için kullanılmak üzere). Varsayılan kesinlik sıfır olduğundan, bu komut dizisi 0sonuç olarak şunları üretir :
2 3 / p
Hassasiyeti ile ayarlayarak k, isteğe bağlı sayıda ondalık basamak üretilebilir. Bu komut dizisi çıktıları .66666.
5 k 2 3 / p
Değerlendirmek için : ( yığının tepesinin karekökünü hesaplar ve negatif bir sayı girmek için kullanılır):
v_
12 _3 4 ^ + 11 / v 22 - p
Yığının en üstteki iki öğesini değiştirmek için rkomutu kullanın. Üst öğeyi çoğaltmak için dkomutu kullanın.
Giriş çıkış
stdin'den bir satır okumak için ?komutu kullanın. Bu, satırı bir dc komutuymuş gibi değerlendirecektir ve bu nedenle sözdizimsel olarak doğru olması ve !dc komutu rastgele komut yürütülmesine izin vereceğinden potansiyel olarak bir güvenlik sorunu olması gerekir .
Yukarıda belirtildiği gibi, pyığının üstünü ondan sonra yeni bir satırla yazdıracaktır. nyığının üstünü açar ve sonunda yeni bir satır olmadan çıkarır. ftüm yığını satır başına bir girişle boşaltacaktır.
dc ayrıca isteğe bağlı giriş ve çıkış köklerini de destekler . iKomut istifinin üst pop ve giriş için temel kullanır. DC komutlarıyla çarpışmaları önlemek için onaltılık rakamlar büyük harf olmalıdır ve AF ile sınırlıdır. oKomut çıkış tabanı için aynısını yapar, ama genellikle ilk çıkış tabanını ayarlamak için tavsiye edilir, böylece girdi tabanı sonradan her sayısal değerin ayrıştırmayı etkileyeceğini unutmayın. Bu nedenle 10o, çıkış tabanını mevcut giriş tabanına ayarlar, ancak genellikle 10 (on) olarak ayarlamaz. Yine de Ao, giriş tabanından bağımsız olarak çıkış tabanını 10 (on) olarak sıfırlar. Değerleri okumak için K, Ive Okomutlar yığının üstüne mevcut hassasiyet, giriş radix ve çıkış radix itecektir.
Örnek olarak, hex'ten ikiliye dönüştürmek için:
$ echo 16i2o DEADBEEFp | dc
11011110101011011011111011101111
Dil özellikleri
Kayıtlar
Bu temel aritmetik ve yığın işlemlerine ek olarak, dc, makrolar , koşullu ifadeler ve daha sonra geri almak için sonuçların saklanması için destek içerir .
Makro ve conditionals altında yatan mekanizma olduğu yazmaç dc depolanır ve alınabilir tek bir karakter adı olan bir depolama konumu,: scyazmacı c yığını ve saklar üst açılır ve lckaydının değerini iter c yığının üzerine. Örneğin:
3 sc 4 lc * p
Kayıtlar ayrıca ikincil yığınlar olarak da değerlendirilebilir, böylece değerler Sve Lkomutları kullanılarak ana yığın arasında itilebilir ve atılabilir .
Teller
Dize değerleri [ve ]karakterleri içine alınır ve yığına itilebilir ve kayıtlarda saklanabilir. aKomut bir içine sayısal değerin düşük sipariş bayt dönüştürür ASCII karakter veya yığının üst bir dize ise o dizenin ilk karakter ile değiştirecektir. Komutla yürütmek xveya komutla yazdırmak dışında, dizeleri oluşturmanın veya dize manipülasyonu gerçekleştirmenin hiçbir yolu yoktur P.
#Karakter satırının sonuna bir yorum başlar.
makrolar
Daha sonra makrolar, kayıtların ve yığın girişlerinin sayılar kadar dizeler olmasına izin verilerek uygulanır. Bir dize yazdırılabilir, ancak yürütülebilir (yani, bir dizi dc komutları olarak işlenebilir). Örneğin, bir makro eklemek için bir makro saklayabilir ve ardından m kaydına 2 ile çarpabiliriz:
[1 + 2 *] sm
ve sonra ( xyığının tepesini yürüten komutu kullanarak ) bunu şu şekilde kullanabiliriz:
3 lm x p
Şartlılar
Son olarak, koşul sağlamak için bu makro mekanizmayı kullanabiliriz. Komut =r, yığından iki değer çıkaracak ve kayıtta saklanan makroyu ryalnızca eşitlerse yürütecektir . Bu, dizeyi equalyalnızca yığının üstü 5'e eşitse yazdıracaktır :
[[equal]p] sm 5 =m
Diğer koşul koşulları , >, !>, <, !<, !=yığındaki ilk iki değer daha büyük, küçük veya eşit ("büyük değil"), küçüktür, büyüktür veya eşittir ("küçük değil") ise belirtilen makroyu yürütür ") ve sırasıyla eşittir. Eşitsizlik karşılaştırmalarında işlenenlerin sırasının aritmetik sırasının tersi olduğuna dikkat edin; 5 3 - 5 - 3 = 2 olarak değerlendirilir, ancak 5 3 <t , t kaydının içeriğini çalıştırır çünkü 3 < 5 .
döngüler
Döngü daha sonra (koşullu olarak) kendisini yeniden çağıran bir makro tanımlayarak mümkündür. Yığının tepesindeki basit bir faktöriyel şu şekilde uygulanabilir:
# F(x): return x! # if x-1 > 1 # return x * F(x-1) # otherwise # return x [d1-d1<F*]dsFxp
1QKomut erken dönüşü sağlayan bir makro çıkacaktır. qiki makro düzeyinden (ve çağrı yığınında ikiden az düzey varsa dc'nin kendisinden) çıkılır. işlemden zönce mevcut yığın derinliğini zzorlar.
Örnekler
Tüm yığını toplamak
Bu, kayıtta saklanan ve akendisini koşullu olarak çağıran, yığında yalnızca bir değer kalana kadar her seferinde bir ekleme gerçekleştiren bir makro ile uygulanır . zOperatör yığına yığındaki girişlerinin sayısını itmek için kullanılır. Karşılaştırma operatörü >, karşılaştırma yaparken yığından iki değer çıkarır.
dc -e "1 2 4 8 16 100 0d[+2z>a]salaxp"
Ve sonuç 131.
Tüm dc ifadelerini dosyadan satırlar olarak toplama
Çıplak sayı geçerli bir dc ifadesidir, bu nedenle bu, her satırın tek bir sayı içerdiği bir dosyayı toplamak için kullanılabilir.
Bu, yine a, yığında yalnızca bir değer kalana kadar, her seferinde bir ekleme gerçekleştirerek, kendisini koşullu olarak çağıran , kayıtta saklanan bir makro ile uygulanır .
cat file | dc -e "0d[?+2z>a]salaxp"
?Operatör girdi akışından başka bir emir okur. Giriş satırı bir ondalık sayı içeriyorsa, bu değer yığına eklenir. Girdi dosyası dosyanın sonuna ulaştığında, komut boştur ve yığına hiçbir değer eklenmez.
{ echo "5"; echo "7"; } | dc -e "0d[?+2z>a]salaxp"
Ve sonuç 12.
Giriş satırları ayrıca karmaşık dc komutları olabilir.
{ echo "3 5 *"; echo "4 3 *"; echo "5dd++"; } | dc -e "0d[?+2z>a]salaxp"
Ve sonuç 42.
DC keyfi kesinliği desteklediğinden, AWK'daki benzer şekilde özlü bir çözümün aksine, giriş akışı kaç satır içeriyor olursa olsun, sayısal taşma veya kesinlik kaybı ile ilgili bir endişe olmadığını unutmayın .
Bu çözümün dezavantajları şunlardır: giriş akışında boş bir satırla karşılaştığında döngü duracaktır (teknik olarak, yığına en az bir sayısal değer eklemeyen herhangi bir giriş satırı); ve negatif sayıları işlemek için, dc'nin standart olmayan negatif işareti nedeniyle, negatif bir işareti belirtmek için baştaki '-' örnekleri giriş akışında '_' olarak değiştirilmelidir. ?Dc içinde operatör dosyasının sonuna okumasını boş satır okuma ayırt etmek temiz bir yol sağlamaz.
Birim dönüştürme
DC'de nispeten basit bir program örneği olarak, bu komut (1 satırda):
dc -e '[[Enter a number (metres), or 0 to exit]psj]sh[q]sz[lhx?d0=z10k39.370079*.5+0k12~1/rn[ feet ]Pn[ inches]P10Pdx]dx'
mesafeleri metreden fit ve inç'e çevirecek; büyük kısmı girdi istemek, çıktıyı uygun bir biçimde yazdırmak ve başka bir sayıyı dönüştürmek için döngü yapmakla ilgilidir.
En büyük ortak böleni
Örnek olarak, burada GCD'yi bulmak için Öklid algoritmasının bir uygulaması verilmiştir :
dc -e '??[dSarLa%d0<a]dsax+p' # shortest
dc -e '[a=]P?[b=]P?[dSarLa%d0<a]dsax+[GCD:]Pp' # easier-to-read version
faktöriyel
Bir giriş değerinin faktöriyelini hesaplamak ,
dc -e '?[q]sQ[d1=Qd1-lFx*]dsFxp'
DC'de Quines
dc programlama dilinde de quines vardır ; kaynak kodunu çıktı olarak üreten programlar.
dc -e '[91Pn[dx]93Pn]dx'
dc -e '[91PP93P[dx]P]dx'
Tüm asal sayıları yazdırma
echo '2p3p[dl!d2+s!%0=@l!l^!<#]s#[s/0ds^]s@[p]s&[ddvs^3s!l#x0<&2+l.x]ds.x' | dc
Bu program Michel Charpentier tarafından yazılmıştır. Asal sayıların sırasını verir. Minimum çözüm gibi görünen bir sembolle kısaltılabileceğini unutmayın.
echo '2p3p[dl!d2+s!%0=@l!l^!<#]s#[0*ds^]s@[p]s&[ddvs^3s!l#x0<&2+l.x]ds.x' | dc
tamsayı çarpanlarına ayırma
dc -e '[n=]P?[p]s2[lip/dli%0=1dvsr]s12sid2%0=13sidvsr[dli%0=1lrli2+dsi!>.]ds.xd1<2'
Bu program aynı zamanda Michel Charpentier tarafından yazılmıştır.
daha kısası var
dc -e "[n=]P?[lfp/dlf%0=Fdvsr]sF[dsf]sJdvsr2sf[dlf%0=Flfdd2%+1+sflr<Jd1<M]dsMx"
ve daha hızlı bir çözüm (200 bitlik sayı 2 200 -1 (giriş 2 200^1-) ile deneyin )
dc -e "[n=]P?[lfp/dlf% 0=Fdvsr]sFdvsr2sfd2%0=F3sfd3%0=F5sf[dlf%0=Flfd4+sflr>M]sN[dlf%0=Flfd2+sflr>N]dsMx[p]sMd1<M"
Bir sabite erişim bir kayıt erişimi ile değiştirilirse, ikincisinin daha da hızlandırılabileceğini unutmayın.
dc -e "[n=]P?[lfp/dlf%l0=Fdvsr]sF2s2dvsr2sf4s4d2%0=F3sfd3%0=F5sf[dlf%l0=Flfdl4+sflr>M]sN[dlf%l0=Flfdl2+sflr>N]dsMx[p]sMd1<M"
Diffie-Hellman anahtar değişimi
Perl betiğine gömülü DC kullanımının daha karmaşık bir örneği, Diffie–Hellman anahtar değişimi gerçekleştirir . Bu, ITAR tartışmaları sırasında cypherpunk'lar arasında bir imza bloğu olarak popülerdi , burada kısa komut dosyası yalnızca Perl ve dc, Unix benzeri işletim sistemlerinde her yerde bulunan programlar ile çalıştırılabilir:
#!/usr/bin/perl -- -export-a-crypto-system-sig Diffie-Hellman-2-lines
($g, $e, $m) = @ARGV, $m || die "$0 gen exp mod\n";
print `echo "16dio1[d2%Sa2/d0<X+d*La1=z\U$m%0]SX$e"[$g*]\EszlXx+p | dc`
Yorumlu bir sürümün anlaşılması biraz daha kolaydır ve döngülerin, koşul ifadelerinin ve qbir makrodan geri dönme komutunun nasıl kullanılacağını gösterir . DC'nin GNU sürümüyle, |komut, X işlevini yazmaya gerek kalmadan isteğe bağlı hassas modüler üs alma yapmak için kullanılabilir.
#!/usr/bin/perl
my ($g, $e, $m) = map { "\U$_" } @ARGV;
die "$0 gen exp mod\n" unless $m;
print `echo $g $e $m | dc -e '
# Hex input and output
16dio
# Read m, e and g from stdin on one line
?SmSeSg
# Function z: return g * top of stack
[lg*]sz
# Function Q: remove the top of the stack and return 1
[sb1q]sQ
# Function X(e): recursively compute g^e % m
# It is the same as Sm^Lm%, but handles arbitrarily large exponents.
# Stack at entry: e
# Stack at exit: g^e % m
# Since e may be very large, this uses the property that g^e % m ==
# if( e == 0 )
# return 1
# x = (g^(e/2)) ^ 2
# if( e % 2 == 1 )
# x *= g
# return x %
[
d 0=Q # return 1 if e==0 (otherwise, stack: e)
d 2% Sa # Store e%2 in a (stack: e)
2/ # compute e/2
lXx # call X(e/2)
d* # compute X(e/2)^2
La1=z # multiply by g if e%2==1
lm % # compute (g^e) % m
] SX
le # Load e from the register
lXx # compute g^e % m
p # Print the result
'`;
Ayrıca bakınız
Referanslar
Dış bağlantılar
- Paket DC içinde Debian GNU / Linux depoları
- – Plan 9 Programcı El Kitabı, Cilt 1
- Yerli Windows portu arasında bc dc içerir.
- bir web sayfasına gömülü dc