Fab'leri ne zaman kullanırım ve std :: abs kullanmak ne zaman yeterlidir?


100

Bunu varsayıyorum absve fabskullanırken farklı davranıyorum math.h. Ama sadece cmathve kullandığımda kullanmak std::abszorunda mıyım std::fabsyoksa fabs? Yoksa bu tanımlanmadı mı?

Yanıtlar:


124

C ++ 'da kullanmak her zaman yeterlidir std::abs; tüm sayısal türler için aşırı yüklenmiş.

C'de absyalnızca tam sayılar üzerinde çalışır ve fabskayan nokta değerlerine ihtiyacınız vardır . Bunlar C ++ 'da mevcuttur (tüm C kitaplığıyla birlikte), ancak bunları kullanmaya gerek yoktur.


Bu her platformda böyle mi? Esp. Windows ve Mac OS X? Yoksa en azından C ++ standardında mı?
matematik

3
@brubelsabs: evet. C ++ 'da işlev aşırı yüklemesine sahip olduğundan (abs birçok tür için tanımlanabilir ve C ++' dadır), C ++ 'da ayrı bir fabs işlevine gerek yoktur. Standart tarafından da garanti edilmektedir. Elbette, biraz araştırırsanız, 10 yaşın üzerinde eski bir derleyici bulursanız, onu desteklemeyen bir tane bulabilirsiniz.
stinky472

1
O yüzden Windows ve Mac OS X Madde 26.5 dahil iyi bir derleyici, her platformda durum ek olarak, diyor, C ++ Standard öyle intC kütüphanesinden sürümü için aşırı yükler vardır long, float, doubleve long double. Madde 26.2.7 aynı zamanda için bir aşırı yük tanımlar complex.
Mike Seymour

6
Unutursanız std::ve sadece kullanırsanız abs, kodunuz Windows'ta beklendiği gibi çalışacaktır ancak intlinux üzerindeki sürümü kullanacaktır , bu da hata ayıklaması inanılmaz derecede zor olabilir.
Adversus

" tüm sayısal türler" [alıntı gerekli]. İnt, long, long long, std :: intmax_t, float, double, long double görebilirim. Görebildiğim kısa veya karakterli sürümler (veya imzasız sürümler) yok.
user673679

23

Hâlâ fabsfor doubleve floatargümanlar kullanmakta sorun yok . O sağlamaktadır çünkü bu tercih ettiklerini yanlışlıkla şerit halinde std::kapalı absdavranış noktası girişlerini yüzen için aynı olduğunu,.

Bunun absyerine kendi hatamdan dolayı, bu sorunu çözmek için 10 dakika harcadım std::abs. Bunun using namespace std;çıkarım yapacağını varsaydım std::absama çıkmadı ve bunun yerine C sürümünü kullanıyordu.

Her neyse, niyetinizi açıkça belgelemenin bir yolu olarak kayan noktalı girdiler fabsyerine kullanmanın iyi olduğuna inanıyorum abs.


2
Bu tuhaf. Aramanız belirsiz (ve dolayısıyla bir hata) olmalıydı, değil mi?
Nick

Float için fabsf kullanmanız gerekmiyor mu? Bu yüzden aynı olduklarını düşünmüyorum.
Nick

Android NDK g ++ konusunda dikkatli olun, ayrıca std :: abs () yerine c abs () işlevine geçer. Visual Studio c ++ derleyicisinde ancak abs her zaman std :: abs () 'ye işaret eder.
southerton

@ Nick, ben sana katılıyorum düşünüyorum: Benim için Alan Turing yani o davranışı elde görünmüyor aşırı std::absdaima çağrılan gibi görünüyor (ve değil C- versiyon abs) ne zaman görüşmesi özelliğini abssürece using namespace std;de açıklanmaktadır başlangıç. Bunun derleyiciye özgü olup olmadığını bilmiyorum.
MaviPranav

@Nick, eşleşen bir işlev adı olduğundan bir hata değildir. Hangisinin seçileceği tanımlanmış uygulamadır.
Pato Sandaña

11

std::fabsKayan noktalı girdileri açıkça önermek için bir neden daha var .

<cmath> eklemeyi unutursanız, yerine sizin std::abs(my_float_num)olabilir . Fark etmesi zor.std::abs(int)std::abs(float)


1

"abs" ve "fabs", belirsiz aşırı yükleme mesajları olmadan çevrilebildiklerinde, yalnızca C ++ kayan tipler için aynıdır.

G ++ (g ++ - 7) kullanıyorum. Şablon kullanımıyla birlikte ve özellikle mpreal kullanırken, zor "belirsiz aşırı yükleme" mesajlarının olduğu durumlar vardır - her zaman bunu çözmez abs(static_cast<T>(x)). Mutlak belirsiz olduğunda, fabrikaların beklendiği gibi çalışma şansı vardır. Sqrt için böyle basit bir kaçış bulamadım.

Haftalardan beri C ++ "mevcut sorunlar değil" konusunda çok mücadele ediyorum. Eskisinden daha fazla ve daha iyi şablon kullanımı için eski bir C ++ programını C ++ 14'e güncelliyorum. Çoğunlukla aynı şablon parametresi gerçek herhangi bir standart kayan nokta veya karmaşık tür veya bir sınıf türü olabilir. Neden, uzun çift, diğer türlerden biraz daha mantıklı davrandı. Her şey çalışıyordu ve daha önce mpreal'ı dahil etmiştim. Sonra varsayılan float tipimi mpreal olarak ayarlıyordum ve bir yığın sözdizimi hatası aldım. Bu, örneğin abs ve sqrt için, farklı çözümler için ağlayan binlerce belirsiz aşırı yüklemeye neden oldu. Bazılarının aşırı yüklenmiş yardım işlevlerine ihtiyacı vardı, ancak bir şablonun dışında. Tek tek bin adet 0.0L ve 1.0L kullanımı, Sıfır veya Bir veya bir type_cast kullanarak tam sabit tip ile değiştirmek zorundaydı - belirsizlikler nedeniyle otomatik dönüşüm tanımı imkansız.

Mayıs ayına kadar, örtük dönüşümlerin varlığını çok güzel buldum. Ama çok daha basitti ve herhangi bir standart sabit tip için güvenli açık tip_castsli tipave sabitlere sahip olmak çok daha basit olurdu.

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.