Nie możesz użyć modułu podwójnego?


185

Mam program w C ++ (skompilowany przy użyciu g ++). Próbuję zastosować dwa podwójne jako operandy do funkcji modułu, ale pojawia się następujący błąd:

błąd: niepoprawne argumenty typu „double” i „double” do binarnego „operatora%”

Oto kod:

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

12
Jak zauważono, fmod () zapewnia niezbędną funkcję. Jak dotychczas nie zauważono, ważne jest, aby zdawać sobie sprawę, że błędy zaokrąglania drugiego argumentu operacji fmodmogą powodować nieoczekiwane zachowania. Na przykład fmod(1, 0.1);powinien matematycznie wynosić zero, ale w rzeczywistości będzie wynosić prawie 0,1. Zakres błędu rośnie wraz z wielkością ilorazu. Na przykład fmod(9E14, 0.1);ocenia na około 0,05, co z matematycznego punktu widzenia jest po prostu błędne.
supercat

1
@ superupat więcej szczegółów byłoby niesamowitych. Myślę, że mam pojęcie o tym, co dzieje się za kulisami, aby spowodować, że to, co mówisz, jest prawdą, ale dobrze byłoby zobaczyć powody, dla których to, co mówisz, jest prawdą; byłoby ciekawie zobaczyć, jak to działa za kulisami (myślę, że rozumiem, ale bardzo łatwo się myliłem).
RastaJedi

3
Wartości zmiennoprzecinkowe reprezentują dokładne wielokrotności całkowite lub ułamki potęg dwóch. Na przykład, literał całkowity 0,1 wynosi dokładnie 3602879701896397/36028797018963968 (ta ostatnia wartość to potęga dwóch). fmod(x,0.1)podzieli x przez tę dokładną część i zajmie resztę, zamiast dzielić przez wartość liczbową „jedna dziesiąta”.
supercat

Odpowiedzi:


272

%Operator jest dla liczb całkowitych. Szukasz fmod()funkcji .

#include <cmath>

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

}

Programuję w C ++ dla Qt i fmod ma tam błąd. Wynik fmod (kąt, 360) może wynosić 360 (WAT ?!)
Paul

7
@Paul: Prawdopodobnie nie jest to błąd. Jeśli angletak, powiedzmy, 359.9999999oba anglei fmod(angle, 360)prawdopodobnie będą wyświetlane jako 360. (W razie potrzeby dodaj więcej 9). Spróbuj wydrukować wartości z, powiedzmy, 50 cyframi dokładności.
Keith Thompson

Format @ Paul Qt QString :: zaokrągli się. Jeśli jest to tak ważne, musisz albo zaokrąglić się, albo sprawdzić wynik dla „360” i zastąpić go własną wartością.
jfh


5

Użyj fmod()od <cmath>. Jeśli nie chcesz dołączać pliku nagłówka C:

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
Dlaczego nie chcesz dołączać pliku nagłówka C? Po to jest.
Keith Thompson

2

W tym celu możesz zaimplementować własną funkcję modułu :

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

Następnie można po prostu użyć dmod(6.3, 2), aby uzyskać pozostałym 0.3.


Nadal nie jest to idealne rozwiązanie. x = 10,499999999999998, y = 0,6999999999999999996 zwraca 0,69999999999999929 zamiast 0,0
tarpista
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.