Почему деление по модулю ( % ) работает только с целыми числами?


Я недавно столкнулся с проблема это можно было легко решить с помощью деления по модулю, но вход был float:

учитывая периодическую функцию (например sin) и компьютерная функция, которая может вычислить ее только в диапазоне периодов (например, [- π, π]), сделать функцию, которая может обрабатывать любые входные данные.

"очевидное" решение-это что-то вроде:

#include <cmath>

float sin(float x){
    return limited_sin((x + M_PI) % (2 *M_PI) - M_PI);
}

Почему это не работает? Я получаю эту ошибку:

error: invalid operands of types double and double to binary operator %

интересно, что он работает в Python:

def sin(x):
    return limited_sin((x + math.pi) % (2 * math.pi) - math.pi)
8 71

8 ответов:

потому что нормальное математическое понятие "остаток" применимо только к целочисленному делению. т. е. деление, которое требуется для генерации целочисленного частного.

чтобы расширить понятие "остаток" до действительных чисел, вы должны ввести новый вид "гибридной" операции, которая будет генерировать целое частное реальные операнды. Язык Core C не поддерживает такую операцию, но он предоставляется как стандартная библиотека fmod

вы ищете fmod ().

Я думаю, чтобы более конкретно ответить на ваш вопрос, в старых языках % оператор был просто определен как целочисленное модульное деление, и в новых языках они решили расширить определение оператора.

EDIT: если бы я поставил догадку, почему, я бы сказал, что это потому, что идея модульной арифметики берет свое начало в теории чисел и имеет дело конкретно с целыми числами.

Я не могу сказать конечно, но я думаю, что это в основном исторический. Довольно много ранних компиляторов C вообще не поддерживали плавающую точку. Он был добавлен позже, и даже тогда не так полностью - в основном тип данных был добавлен, и большинство примитивные операции поддерживаются в языке, но все остальное осталось в стандартной библиотеке.

деление с остатком % в C и C++ определяется для двух целых чисел, однако, есть fmod() функция доступна для использования с двойниками.

ограничения находятся в стандартах:

C11 (ISO/IEC 9899:201x) §6.5.5 мультипликативных операторов

каждый из операндов должен иметь арифметический тип. Операнды оператора % должны имеют целочисленный тип.

C++11 (ISO/IEC 14882:2011) §5.6 мультипликативных операторов

операнды * и / должны иметь арифметический или перечислительный тип; операнды % должны иметь Интеграл или перечисления тип. Обычные арифметические преобразования выполняются на операндах и определяют тип результата.

решение заключается в использовании fmod именно поэтому операнды % ограничены целочисленным типом в первую очередь, согласно C99 Обоснование §6.5.5 мультипликативных операторов:

комитет C89 отклонил расширение оператора % для работы с плавающими типами как таковыми использование будет дублировать объект, предоставленный fmod

попробовать fmod

оператор % дает вам остаток (другое имя для модуля) числа. Для C / C++ это определяется только для целочисленных операций. Python немного шире и позволяет получить остаток числа с плавающей запятой для остатка того, сколько раз число можно разделить на него:

>>> 4 % math.pi
0.85840734641020688
>>> 4 - math.pi
0.85840734641020688
>>> 

The % оператор не работает в C++, когда вы пытаетесь найти остаток от двух чисел, которые являются оба типа Float или Double.

следовательно, вы можете попробовать использовать