Non è possibile utilizzare il modulo sui doppi?


185

Ho un programma in C ++ (compilato usando g ++). Sto cercando di applicare due doppi come operandi alla funzione modulo, ma ottengo il seguente errore:

errore: operandi non validi di tipo 'double' e 'double' in binary 'operator%'

Ecco il codice:

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

12
Come è stato notato, fmod () fornisce la funzione necessaria. Come non è stato ancora notato, è importante rendersi conto che gli errori di arrotondamento nel secondo operando di fmodpossono causare comportamenti imprevisti. Ad esempio, fmod(1, 0.1);dovrebbe essere matematicamente zero, ma in realtà sarà quasi 0,1. L'entità dell'errore aumenta con l'entità del quoziente. Ad esempio, fmod(9E14, 0.1);valuta circa 0,05, che è da un punto di vista matematico semplicemente sbagliato.
supercat,

1
@supercat maggiori dettagli sarebbero fantastici. Penso che abbia un'idea di cosa ci sia dietro le quinte per far sì che ciò che dici sia vero, ma sarebbe bello vedere i motivi per cui ciò che dici è vero; sarebbe interessante vedere come funziona dietro le quinte (penso di capire ma potrei sbagliarmi facilmente).
RastaJedi

3
I valori a virgola mobile rappresentano multipli interi esatti o frazioni di potenze di due. Ad esempio, l'intero valore letterale 0.1 è esattamente 3602879701896397/36028797018963968 (quest'ultimo valore è una potenza di due). fmod(x,0.1)dividerà x per quella frazione precisa e prenderà il resto, anziché dividere per il valore numerico "un decimo".
supercat

Risposte:


272

L' %operatore è per numeri interi. Stai cercando la fmod()funzione .

#include <cmath>

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

}

Sto programmando in C ++ per Qt e fmod ha un bug lì. Il risultato di fmod (angolo, 360) può essere 360 ​​(WAT ?!)
Paul

7
@Paul: probabilmente non è un bug. Se angleè, diciamo, 359.9999999allora entrambi anglee fmod(angle, 360)probabilmente verranno visualizzati come 360. (Aggiungi altri 9 secondi se necessario.) Prova a stampare i valori con, diciamo, 50 cifre di precisione.
Keith Thompson,

Il formato QString :: @Paul Qt verrà arrotondato. Se è così critico, dovrai arrotondare te stesso o controllare l'output per "360" e sostituirlo con il tuo valore.
jfh

38

fmod(x, y) è la funzione che usi.


5

Utilizzare fmod()da <cmath>. Se non si desidera includere il file di intestazione 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
Perché non dovresti voler includere il file di intestazione C? Ecco a cosa serve.
Keith Thompson,

2

Puoi implementare la tua funzione di modulo per farlo per te:

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

Poi si può semplicemente utilizzare dmod(6.3, 2)per ottenere il resto, 0.3.


Non è ancora una soluzione perfetta. x = 10.499999999999998, y = 0.69999999999999996 restituisce 0.6999999999999999929 invece di 0.0
tarpista
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.