Por que o operador de módulo não está funcionando para o dobro em c #?

Considere isto:

double x,y; x =120.0; y = 0.05; double z= x % y; 

Eu tentei isso e esperava que o resultado fosse 0, mas saiu 0.04933333.

Contudo,

 x =120.0; y = 0.5; double z= x % y; 

De fato deu o resultado correto de 0.

O que esta acontecendo aqui?

Eu tentei o Math.IEEERemainder(double, double) mas ele não está retornando 0 também. O que está acontecendo aqui?

Além disso, como um aparte, qual é a maneira mais adequada para encontrar o restante em c #?

Devido ao seu formato de armazenamento, os double s não podem armazenar todos os valores exatamente como estão inseridos ou exibidos. A representação humana dos números é geralmente em formato decimal, enquanto os double são baseados no sistema dual.

Em um double , 120 é armazenado precisamente porque é um valor inteiro. Mas 0.05 não é. O dobro é aproximado ao número mais próximo de 0.05 ele pode representar. 0.5 é uma potência de 2 ( 1/2 ), portanto, pode ser armazenada com precisão e você não recebe um erro de arredondamento.

Para ter todos os números exatamente da mesma maneira que você entra / exibe no sistema decimal, use decimal .

 decimal x, y; x = 120.0M; y = 0.05M; decimal z = x % y; // z is 0 

Você poderia fazer algo como:

 double a, b, r; a = 120; b = .05; r = a - Math.floor(a / b) * b; 

Isso deve ajudar;)

Eu acredito que se você tentasse o mesmo com o decimal funcionaria corretamente.

Módulo só deve ser usado com inteiro. O restante vem de uma divisão euclidiana. Com o dobro, você pode ter resultados inesperados.

Veja este artigo

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems pode ajudá-lo a entender por que você obtém esses resultados “estranhos”. Há uma precisão específica que os números de ponto flutuante podem ter. Apenas tente estas consultas e dê uma olhada nos resultados:

0,5 na base 2

0,05 na base 2