Çiftler üzerinde modül kullanamaz mısınız?


185

C ++ (g ++ kullanarak derlenmiş) bir program var. Ben modül işlevi için işlenen olarak iki çift uygulamak çalışıyorum, ancak aşağıdaki hatayı alıyorum:

hata: 'double' ve 'double' türlerinin geçersiz işlenenleri ile ikili 'operatör%'

İşte kod:

int main() {
    double x = 6.3;
    double y = 2;
    double z = x % y;
}

12
Daha önce belirtildiği gibi, fmod () gerekli işlevi sağlar. Daha önce belirtilmemiş olduğu gibi, ikinci işlenenindeki yuvarlama hatalarının fmodbeklenmedik davranışlara neden olabileceğini anlamak önemlidir . Örneğin, fmod(1, 0.1);matematiksel olarak sıfır olmalıdır, ancak aslında neredeyse 0.1 olacaktır. Hatanın derecesi, bölümün büyüklüğü ile artar. Örneğin, fmod(9E14, 0.1);matematiksel açıdan sadece yanlış olan yaklaşık 0.05'e değerlendirir.
supercat

1
@supercat daha fazla detay harika olurdu. Bence söylediklerinizin doğru olmasına neden olmak için perde arkasında neler olduğu hakkında bir fikrim var, ama söylediklerinizin doğru olmasının nedenlerini görmek iyi olurdu; perde arkasında nasıl çalıştığını görmek ilginç olurdu (sanırım anlıyorum ama çok kolay bir şekilde yanlış olabilir).
RastaJedi

3
Kayan nokta değerleri tam tam sayı katlarını veya ikisinin kuvvet kesirlerini temsil eder. Örneğin, tam sayı 0,1 tam olarak 3602879701896397/36028797018963968'dir (son değer iki güçtür). fmod(x,0.1)x'i "onda biri" sayısal değerine bölmek yerine, o kesin kesri böler ve kalanını alır.
Supercat

Yanıtlar:


272

%Operatör tamsayılar içindir. fmod()İşlevi arıyorsunuz .

#include <cmath>

int main()
{
    double x = 6.3;
    double y = 2.0;
    double z = std::fmod(x,y);

}

Qt için C ++ programlama ve fmod orada bir hata var. Fmod'un (açı, 360) sonucu 360 (WAT ?!) olabilir
Paul

7
@ Paul: Bu muhtemelen bir hata değil. Öyleyse angle, diyelim ki, 359.9999999her ikisi de angleve fmod(angle, 360)olarak görüntülenir 360. (Gerektiğinde daha fazla 9 saniye ekleyin.) Değerleri, örneğin 50 basamak hassasiyetle yazdırmayı deneyin.
Keith Thompson

@Paul Qt'ın QString :: biçimi yuvarlanır. Eğer bu kritikse, ya kendinizi yuvarlamanız ya da çıktıyı "360" için kontrol etmeniz ve kendi değerinizle değiştirmeniz gerekecektir.
jfh

38

fmod(x, y) kullandığınız işlevdir.


5

Kullan fmod()dan <cmath>. C başlık dosyasını dahil etmek istemiyorsanız:

template<typename T, typename U>
constexpr double dmod (T x, U mod)
{
    return !mod ? x : x - mod * static_cast<long long>(x / mod);
}

//Usage:
double z = dmod<double, unsigned int>(14.3, 4);
double z = dmod<long, float>(14, 4.6);
//This also works:
double z = dmod(14.7, 0.3);
double z = dmod(14.7, 0);
double z = dmod(0, 0.3f);
double z = dmod(myFirstVariable, someOtherVariable);

3
Neden C başlık dosyasını dahil etmek istemiyorsunuz? Bunun için orada.
Keith Thompson

2

Bunu yapmak için kendi modül işlevinizi uygulayabilirsiniz :

double dmod(double x, double y) {
    return x - (int)(x/y) * y;
}

Sonra sadece dmod(6.3, 2)kalanını almak için kullanabilirsiniz 0.3.


Hala mükemmel bir çözüm değil. x = 10.499999999999998, y = 0,69999999999999996 0,0 yerine 0,9999999999999929 döndürür
tarpista
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.