Mod com Duplas

Estou fazendo algo errado ou o operador VBA Mod na verdade não funciona com valores de ponto flutuante como Doubles?

Então, eu sempre achei que o operador VBA Mod funcionaria com o Doubles com base noDocumentação VB, mas, ao tentar descobrir por que minha função de arredondamento não funciona, encontrei um comportamento inesperado do Mod.

Aqui está o meu código:

Public Function RoundUp(num As Double, Optional nearest As Double = 1)
    RoundUp = ((num \ nearest) - ((num Mod nearest) > 0)) * nearest
End Function

RoundUp(12.34) retorna12 ao invés de13 então eu cavei um pouco mais fundo e descobri que:

12.5 Mod 1 retorna0 com o tipo de retorno Long, enquanto eu esperava 0,5 com um tipo de Double.

Conclusão

Como@ ckuhn203 aponta em sua resposta, de acordo com a especificação VBA,

O operador de módulo ou restante divide o número1 pelo número2 (arredondando números de ponto flutuante para números inteiros) e retorna apenas o restante como resultado.

E

Normalmente, o tipo de dado do resultado é um Byte, Variante de byte, Inteiro, Variante de número inteiro, Longo ou Variante contendo um Longo, independentemente de o resultado ser ou não um número inteiro. Qualquer parte fracionária é truncada.

Para meus propósitos, preciso de um módulo de ponto flutuante e, por isso, decidi usar o seguinte:

Public Function FMod(a As Double, b As Double) As Double
    FMod = a - Fix(a / b) * b

    'http://en.wikipedia.org/wiki/Machine_epsilon
    'Unfortunately, this function can only be accurate when `a / b` is outside [-2.22E-16,+2.22E-16]
    'Without this correction, FMod(.66, .06) = 5.55111512312578E-17 when it should be 0
    If FMod >= -2 ^ -52 And FMod <= 2 ^ -52 Then '+/- 2.22E-16
        FMod = 0
    End If
End Function

aqui estão alguns exemplos:

FMod(12.5, 1) = 0.5 FMod(5.3, 2) = 1.3 FMod(18.5, 4.2) = 1.7

Usar isso na minha função de arredondamento resolve meu problema específico.

questionAnswers(2)

yourAnswerToTheQuestion