Tidak dapat menggunakan modulus pada ganda?

185

Saya punya program di C ++ (dikompilasi menggunakan g ++). Saya mencoba menerapkan dua ganda sebagai operan ke fungsi modulus, tetapi saya mendapatkan kesalahan berikut:

kesalahan: operan tidak valid dari tipe 'ganda' dan 'ganda' ke biner 'operator%'

Berikut kodenya:

int main() {
    double x = 6.3;
    double y = 2;
    double z = x % y;
}
Bhaxy
sumber
12
Seperti yang telah dicatat, fmod () menyediakan fungsi yang diperlukan. Seperti yang belum dicatat, penting untuk menyadari bahwa kesalahan pembulatan dalam operan kedua fmoddapat menyebabkan perilaku yang tidak terduga. Sebagai contoh, secara fmod(1, 0.1);matematis harus nol, tetapi pada kenyataannya hampir 0,1. Tingkat kesalahan naik dengan besarnya hasil bagi. Sebagai contoh, fmod(9E14, 0.1);mengevaluasi menjadi sekitar 0,05, yang dari sudut pandang matematika jelas salah.
supercat
1
@supercat detail lebih lanjut akan luar biasa. Saya pikir punya ide tentang apa yang ada di balik layar untuk menyebabkan apa yang Anda katakan itu benar, tetapi akan baik untuk melihat alasan mengapa apa yang Anda katakan itu benar; akan menarik untuk melihat cara kerjanya di belakang layar (saya pikir saya mengerti tetapi bisa sangat mudah salah).
RastaJedi
3
Nilai floating-point mewakili kelipatan integer yang tepat atau fraksi kekuatan dua. Misalnya, integer literal 0,1 persis 3602879701896397/36028797018963968 (nilai yang terakhir adalah kekuatan dua). fmod(x,0.1)akan membagi x dengan fraksi yang tepat dan mengambil sisanya, daripada membaginya dengan nilai numerik "sepersepuluh".
supercat

Jawaban:

272

The %operator adalah untuk bilangan bulat. Anda sedang mencari fmod()fungsinya .

#include <cmath>

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

}
Mistikal
sumber
Saya pemrograman dalam C ++ untuk Qt dan fmod memiliki bug di sana. Hasil dari fmod (sudut, 360) bisa menjadi 360 (WAT ?!)
Paul
7
@ Paul: Itu mungkin bukan bug. Jika angle, katakanlah, 359.9999999maka keduanya angledan fmod(angle, 360)kemungkinan akan ditampilkan sebagai 360. (Tambahkan lebih banyak angka 9 sesuai kebutuhan.) Coba cetak nilainya dengan, katakanlah, 50 digit presisi.
Keith Thompson
@Paul Qt's QString :: format akan dibulatkan. Jika itu sangat penting, Anda harus membulatkan diri sendiri atau memeriksa output untuk "360" dan menggantinya dengan nilai Anda sendiri.
jfh
38

fmod(x, y) adalah fungsi yang Anda gunakan.

MSN
sumber
5

Gunakan fmod()dari <cmath>. Jika Anda tidak ingin menyertakan file header 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);
Jule yang skeptis
sumber
3
Mengapa Anda tidak ingin menyertakan file header C? Untuk itulah ia ada.
Keith Thompson
2

Anda dapat mengimplementasikan fungsi modulus Anda sendiri untuk melakukannya untuk Anda:

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

Maka Anda cukup menggunakan dmod(6.3, 2)untuk mendapatkan sisanya 0.3,.

Mistik
sumber
Masih bukan solusi yang sempurna. x = 10.499999999999998, y = 0,69999999999999996 mengembalikan 0,6999999999999999929 bukan 0,0
tarpista