Mod双打

Bla*_*awk 11 double ms-access vba modulus

我做错了什么,或者VBA Mod操作符实际上不适用于像双打这样的浮点值?

所以我总是假设VBA Mod操作符可以使用基于VB文档的 Doubles ,但是在试图弄清楚为什么我的舍入函数不起作用时,我发现了一些意想不到的Mod行为.

这是我的代码:

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

RoundUp(12.34)返回12而不是13如此我挖得更深一些,发现:

12.5 Mod 1返回0类型为Long的返回类型,而我的预期值为0.5,类型为Double.


结论

正如@ ckuhn203在答案中指出的那样,根据VBA规范,

模数或余数运算符将number1除以number2(将浮点数舍入为整数),并仅返回余数作为结果.

通常,结果的数据类型是包含Long的Byte,Byte变量,Integer,Integer变量,Long或Variant,而不管结果是否为整数.任何小数部分都被截断.

为了我的目的,我需要一个浮点模数,所以我决定使用以下内容:

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
Run Code Online (Sandbox Code Playgroud)

这里有些例子:

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

在我的舍入函数中使用它解决了我的特定问题.

Rub*_*uck 10

根据VB6/VBA文档

模数或余数运算符将number1除以number2(将浮点数舍入为整数),并仅返回余数作为结果.例如,在下面的表达式中,A(结果)等于5. A = 19 Mod 6.7通常,结果的数据类型是包含Long的Byte,Byte变量,Integer,Integer变量,Long或Variant,无论是否或不结果是一个整数.任何小数部分都被截断.但是,如果任何表达式为Null,则结果为Null.任何为Empty的表达式都被视为0.

记住,mod返回除法的余数.任何整数 mod 1 = 0.

debug.print 12 mod 1 
'12/1 = 12 r 0
Run Code Online (Sandbox Code Playgroud)

这里真正的罪魁祸首是vba 执行模数之前将double翻转(舍入)为整数.

?13 mod 10
 '==>3 
?12.5 mod 10
 '==>2 

debug.print 12.5 mod 1
'vba truncates 12.5 to 12
debug.print 12 mod 1
'==> 0
Run Code Online (Sandbox Code Playgroud)

  • 在互联网上闲逛之后,似乎在许多语言中,mod运算符仅适用于整数值。一些具有诸如“ fmod”之类的单独功能来执行浮点模数。很少有同时执行两者的mod运算符。[维基百科按语言列出了很好的整数/浮点模函数列表](http://en.wikipedia.org/wiki/Modulo_operation) (2认同)