Не можете использовать модуль на двойниках?


185

У меня есть программа на C ++ (скомпилирована с использованием g ++). Я пытаюсь применить два двойных в качестве операндов к функции модуля, но я получаю следующую ошибку:

ошибка: недопустимые операнды типов 'double' и 'double' для двоичного оператора '%'

Вот код:

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

12
Как уже было отмечено, fmod () обеспечивает необходимую функцию. Как еще не было отмечено, важно понимать, что ошибки округления во втором операнде fmodмогут вызывать неожиданное поведение. Например, fmod(1, 0.1);математически должно быть ноль, но на самом деле будет почти 0,1. Степень ошибки возрастает с величиной фактора. Например, fmod(9E14, 0.1);оценивается примерно до 0,05, что с математической точки зрения просто неправильно.
суперкат

1
@supercat больше деталей было бы здорово. Я думаю, что есть представление о том, что происходит за кулисами, чтобы заставить то, что вы говорите, быть правдой, но было бы хорошо увидеть причины того, почему то, что вы говорите, является правдой; было бы интересно посмотреть, как это работает за кулисами (думаю, я понимаю, но могу очень легко ошибаться).
RastaJedi

3
Значения с плавающей точкой представляют собой точные целые числа или доли степеней двух. Например, целочисленный литерал 0.1 в точности равен 3602879701896397/36028797018963968 (последнее значение является степенью двойки). fmod(x,0.1)будет делить x на эту точную дробь и брать остаток, а не делить на числовое значение «одна десятая».
суперкат

Ответы:


272

%Оператор для целых чисел. Вы ищете fmod()функцию .

#include <cmath>

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

}

Я программирую на C ++ для Qt, и в fmod есть ошибка. Результат fmod (угол 360) может быть 360 (WAT ?!)
Пол

7
@ Пол: Это, вероятно, не ошибка. Если angle, скажем, 359.9999999то и то angleи другое fmod(angle, 360), скорее всего, будет отображаться как 360. (При необходимости добавьте еще 9 с.) Попробуйте напечатать значения, скажем, с точностью до 50 цифр.
Кит Томпсон

Формат QString :: @Paul Qt округляется. Если это так важно, вам придется либо округлить себя, либо проверить выходное значение «360» и заменить его своим собственным значением.
JFH

38

fmod(x, y) это функция, которую вы используете.


5

Используйте fmod()от <cmath>. Если вы не хотите включать заголовочный файл 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
Почему вы не хотите включать заголовочный файл C? Вот для чего это.
Кит Томпсон

2

Вы можете реализовать свою собственную функцию модуля для этого:

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

Тогда вы можете просто использовать, dmod(6.3, 2)чтобы получить остаток 0.3.


Все еще не идеальное решение. х = 10,499999999999998, у = 0,69999999999999996 возвращает 0,69999999999999929 вместо 0,0
тарписта
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.