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

185

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

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

Вот код:

int main() {
    double x = 6.3;
    double y = 2;
    double z = x % y;
}
Bhaxy
источник
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);

}
Mysticial
источник
Я программирую на 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) это функция, которую вы используете.

MSN
источник
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
тарписта