Không thể sử dụng mô-đun trên đôi?


184

Tôi có một chương trình trong C ++ (được biên dịch bằng g ++). Tôi đang cố gắng áp dụng hai nhân đôi là toán hạng cho hàm mô đun, nhưng tôi gặp lỗi sau:

lỗi: toán hạng không hợp lệ của loại 'double' và 'double' thành nhị phân 'toán tử%'

Đây là mã:

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

12
Như đã lưu ý, fmod () cung cấp hàm cần thiết. Như chưa được lưu ý, điều quan trọng là phải nhận ra rằng các lỗi làm tròn trong toán hạng thứ hai fmodcó thể gây ra các hành vi không mong muốn. Ví dụ, fmod(1, 0.1);về mặt toán học nên bằng 0, nhưng thực tế sẽ gần như 0,1. Mức độ lỗi đi lên với độ lớn của thương. Ví dụ, fmod(9E14, 0.1);đánh giá khoảng 0,05, từ quan điểm toán học chỉ đơn giản là sai.
supercat

1
@supercat thêm chi tiết sẽ là tuyệt vời. Tôi nghĩ có một ý tưởng về những gì đằng sau hậu trường để khiến những gì bạn nói là đúng, nhưng sẽ tốt hơn nếu thấy những lý do tại sao những gì bạn nói là đúng; sẽ rất thú vị khi xem cách nó hoạt động đằng sau hậu trường (tôi nghĩ tôi hiểu nhưng rất dễ bị sai).
RastaJedi 18/03/2016

3
Các giá trị dấu phẩy động biểu thị bội số nguyên chính xác hoặc phân số lũy thừa của hai số. Ví dụ: số nguyên 0,1 chính xác là 3602879701896397/36028797018963968 (giá trị sau là lũy thừa của hai). fmod(x,0.1)sẽ chia x cho phân số chính xác đó và lấy phần còn lại, thay vì chia cho giá trị số "một phần mười".
supercat

Câu trả lời:


272

Các %nhà điều hành là dành cho số nguyên. Bạn đang tìm kiếm fmod()chức năng .

#include <cmath>

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

}

Tôi đang lập trình trong C ++ cho Qt và fmod có lỗi ở đó. Kết quả của fmod (angle, 360) có thể là 360 (WAT?!)
Paul

7
@Paul: Đó có lẽ không phải là một lỗi. Nếu anglelà, giả sử, 359.9999999thì cả hai anglefmod(angle, 360)có khả năng được hiển thị là 360. (Thêm 9 giây nữa nếu cần.) Thử in các giá trị với độ chính xác 50 chữ số.
Keith Thompson

Định dạng QString :: của @Paul Qt sẽ làm tròn. Nếu nó rất quan trọng, bạn sẽ phải tự làm tròn hoặc kiểm tra đầu ra cho "360" và thay thế nó bằng giá trị của riêng bạn.
jfh

38

fmod(x, y) là chức năng bạn sử dụng.


5

Sử dụng fmod()từ <cmath>. Nếu bạn không muốn bao gồm tệp tiêu đề 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
Tại sao bạn không muốn bao gồm tệp tiêu đề C? Đó là những gì nó ở đó cho.
Keith Thompson

2

Bạn có thể thực hiện chức năng mô đun của riêng mình để làm điều đó cho bạn:

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

Sau đó, bạn có thể chỉ cần sử dụng dmod(6.3, 2)để có được phần còn lại , 0.3.


Vẫn không phải là một giải pháp hoàn hảo. x = 10,499999999999998, y = 0,69999999999999996 trả về 0,69999999999999929 thay vì 0,0
tarpista
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.