Não é possível usar o módulo em duplas?

185

Eu tenho um programa em C ++ (compilado usando g ++). Estou tentando aplicar dois duplos como operandos à função de módulo, mas recebo o seguinte erro:

error: operandos inválidos dos tipos 'double' e 'double' para o operador binário '%'

Aqui está o código:

int main() {
    double x = 6.3;
    double y = 2;
    double z = x % y;
}
Bhaxy
fonte
12
Como foi observado, fmod () fornece a função necessária. Como ainda não foi observado, é importante perceber que os erros de arredondamento no segundo operando de fmodpodem causar comportamentos inesperados. Por exemplo, fmod(1, 0.1);matematicamente deve ser zero, mas na verdade será quase 0,1. A extensão do erro aumenta com a magnitude do quociente. Por exemplo, fmod(9E14, 0.1);avalia em cerca de 0,05, o que é do ponto de vista matemático completamente errado.
precisa
1
@supercat mais detalhes seria incrível. Eu acho que tenho uma idéia do que está nos bastidores para fazer com que o que você diz seja verdade, mas seria bom ver as razões pelas quais o que você diz é verdade; seria interessante ver como funciona nos bastidores (acho que entendo, mas poderia facilmente estar errado).
RastaJedi 18/03/16
3
Os valores de ponto flutuante representam múltiplos inteiros exatos ou frações de potência de dois. Por exemplo, o literal inteiro 0.1 é exatamente 3602879701896397/36028797018963968 (o último valor é uma potência de dois). fmod(x,0.1)dividirá x por essa fração precisa e ficará com o restante, em vez de dividir pelo valor numérico "um décimo".
Supercat

Respostas:

272

O %operador é para números inteiros. Você está procurando a fmod()função .

#include <cmath>

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

}
Mysticial
fonte
Estou programando em C ++ para Qt e fmod tem um bug lá. O resultado da fmod (ângulo, 360) pode ser 360 (WAT ?!)
Paul
7
@ Paul: Isso provavelmente não é um bug. Se anglefor, digamos, 359.9999999ambos anglee fmod(angle, 360)provavelmente serão exibidos como 360. (Adicione mais 9s conforme necessário.) Tente imprimir os valores com, digamos, 50 dígitos de precisão.
18120 Keith Thompson
O formato QString :: do @Paul Qt :: será arredondado. Se isso for crítico, você precisará arredondar a si próprio ou verificar a saída em "360" e substituí-la por seu próprio valor.
jfh 26/03
38

fmod(x, y) é a função que você usa.

MSN
fonte
5

Use fmod()de <cmath>. Se você não deseja incluir o arquivo de cabeçalho 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 cético
fonte
3
Por que você não deseja incluir o arquivo de cabeçalho C? É para isso que serve.
18130 Keith Thompson
2

Você pode implementar sua própria função de módulo para fazer isso por você:

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

Então você pode simplesmente usar dmod(6.3, 2)para obter o restante 0.3,.

Místico
fonte
Ainda não é uma solução perfeita. x = 10.499999999999998, y = 0.69999999999999996 retorna 0,69999999999999929 em vez de 0,0
tarpista