函数 MOD 上的 Excel 错误

Posted

技术标签:

【中文标题】函数 MOD 上的 Excel 错误【英文标题】:Excel error on function MOD 【发布时间】:2016-06-22 11:13:32 【问题描述】:

我想在我的 excel 文件中输入这个公式(最好是 VBA)。但是由于某种原因,当我将此函数放在我的公式栏中时出现错误:

#NUM! - Number Error

我的功能是:

=98-mod(2000000000123456*100;97))

但是当我只输入 10 位数字时,它就可以工作了。我需要使用 16 位数字。 我基本上是在尝试根据 ISO 7064 Mod 97,10 公式验证数字 提前致谢。

感谢大家的努力,但我尝试了@Robyn 编写的代码,但出现溢出错误。这是我的代码(我将只写函数部分): '注:输入参数为:3259300700853850和97

 Function DblMod(Dividend, Divisor)
' Declare two double precision variables
Dim D1 As Double
Dim D2 As Double
' Copy function arguments to local variables
D1 = Dividend
D2 = Divisor
DblMod = D1 Mod D2
End Function

【问题讨论】:

但 Excel 只能处理 15 位数字。 @Gary'sStudent 我倾向于指定:你可以enter and use much larger numbers。但如果超过 15 位的精度很重要,则不应使用 Excel:superuser.com/questions/373997/… 我相信我的解决方案会适用于您的情况。 你能说出3259300700853850(除数)和97(除数)的正确答案吗? 赏金描述中的所有例子都有错误的结果。 98-mod(3100400300327166;97)=50 但是 98-mod(3100400300327166*100;97)=51,你有来自@RonRosenfeld 的正确答案,如果它不起作用 - 你必须详细描述原因。 【参考方案1】:

如前所述,Excel 有 15 位精度的限制。因此,当您输入上面的公式时,您的 16 位数字将被更改:

2000000000123456 变为 2000000000123460

解决此限制的一种方法是使用 VBA 并更改您的公式。

不要写16 digit number * 100,而是输入整个值作为字符串:

“200000000012345600”

例如:

=98-xMOD("200000000012345600";97)

然后使用这个 UDF,它利用 VBA 的 Decimal 数据类型提供的更高精度:

Option Explicit
Function xMOD(Num As Variant, Div As Long)
    Dim x As Variant, y As Variant

x = CDec(Num)
y = CDec(Div)

xMOD = x - Int(x / y) * y

End Function

如果您要在某个单元格中输入 16 位数字(作为字符串),并且始终乘以 100,则可以使用以下公式:

=98-xMOD(C1&"00";97)

或者,您可以将 18 位数字作为字符串输入某个单元格并在公式中引用它,省略 &"00" 部分。

如果你能找到它,另一个选项是一个不受支持的免费插件,名为xNumbers。最新版本6.0 仍然适用于 Excel 2016,尽管不存在与功能区的集成,因此无法使用某些配置选项。

编辑既然你写到你无法让这个 UDF 在你的系统中工作,我将发布一个屏幕截图,显示它在我的系统中工作,并且它与结果一致您已在赏金说明中发布。 (来自 xNumbers 的 xIntMod 也返回相同的结果)

【讨论】:

不幸的是它不允许我运行这个函数,“你输入的公式包含错误”。 @Stefan0309 您是否为您的区域设置使用了正确的系统分隔符信号。分号与逗号句号 @Stefan0309 您是否检查过您的系统分隔符,您使用的分隔符是否适合您的语言环境?如果正确,请复制并粘贴(不要输入)您的确切公式和公式所引用的数据,或者最好上传显示问题的工作簿并在此处发布链接。 智能解决方案,您甚至可以将函数精简到一行,即 'xMOD = CDec(Num) - Int(CDec(Num) / CDec(Div)) * CDec(Div)' @EEM 谢谢。一个班轮很有趣,但它们有时会使算法更难破译。我从未测试过一种方式是否比另一种方式有任何速度优势。【参考方案2】:

对于 abs() 小于或等于 2,147,483,647 的数字

这是 Microsoft 支持文章 XL: MOD() Function Returns #NUM! Error Value 中的一个已知问题。

请注意,这篇文章已经过时了 - 因此这可能不是您的实例的真正根本原因。

文章建议以下解决方法:

不要使用这个公式=MOD(J13,K13),而是使用这个公式:=J13-(INT(J13/K13)*K13)

或者,this article 建议使用 VBA 等效项:

Function DblMod(Dividend, Divisor)
    ' Declare two double precision variables
    Dim D1 As Double
    Dim D2 As Double

    ' Copy function arguments to local variables
    D1 = Dividend
    D2 = Divisor

    DblMod = D1 Mod D2
End Function

对于 abs() 大于 2,147,483,647 的数字

在这种情况下,VBA MOD 函数溢出Run Time Error '6': Overflow。这在 Microsoft 支持文章 PRB: "Overflow" with Integer Division and MOD Operator 中得到解决。这篇文章在 VBA 中提出了以下解决方案,我已经测试过它可以使用 OP 的给定数字按预期工作:

Sub Main()
    Call DblMod2(3259300700853850, 97) 
    ' returns 46, which matches the Big Integer Calculator at http://www.javascripter.net/math/calculators/100digitbigintcalculator.htm suggested by Ron
End Sub

Function DblMod2(Dividend, Divisor)

    Dim dblX As Double
    Dim dblY As Double
    dblX = Dividend               ' numerator
    dblY = Divisor                ' denominator

    ' round off the numerator and denominator (ensure number is .0)
    dblX = Int(dblX + 0.5)
    dblY = Int(dblY + 0.5)

    ' Emulate integer division with: Fix(dblX / dblY)
    ' Emulate modulo arithmetic with: dblX - (dblY * Fix(dblX / dblY))
    DblMod2 = dblX - (dblY * Fix(dblX / dblY))
    Debug.Print DblMod2
End Function

【讨论】:

我试过这个 vba 代码,但它返回一个溢出错误。我不确定这是否正确? 由于 OP 想要处理 16 位数字,您的解决方案都无法正常工作 我认为 Excel 可以处理非常长的数字 - 只是需要注意不精确 - 所以我进一步挖掘。我会尽快更新我建议的解决方案。 嗨@Stefan0309,我建议的解决方案已在上面更新。这给了我预期的数字(在 Excel 2013 中)。 但是您正在测试的号码是200,000,000,012,346,000,而OP帖子中的号码是200,000,000,012,345,600【参考方案3】:

MOD函数here有一个替代方法

a - (b * (a / b))

=98-((2000000000123450*100)-(97*((2000000000123450*100)/97)))

编辑 1

试试下面,它会返回 46

Function DblMod(Dividend, Divisor)
    ' Declare two double precision variables
    Dim D1 As Double
    Dim D2 As Double
    Dim D3 As Double
    Dim str1
    Dim Str2
    ' Copy function arguments to local variables
    D1 = CDbl(Dividend)
    D2 = Divisor
    DblMod = CDec(D1) - (Round(CDec(D1) / D2) * D2)
End Function

Sub test()
    test = DblMod("3259300700853850", 97)
End Sub

【讨论】:

请注意,OP 的 16 位数字中的最后一位已更改【参考方案4】:

不要处理非常大的数字,只需像这样拆分它们:

Public Function ExtMod(Dividend As String, Divisor As Long) As Double
  Dim i As Long, j As Double
  For i = 1 To Len(Dividend)
    If Not IsNumeric(Mid(Dividend, i, 1)) Then
      j = j & Mid(Dividend, i)
      Exit For
    End If
    j = j * 10 + Mid(Dividend, i, 1)
    While j >= Divisor
      j = j - Divisor
    Wend
  Next
  ExtMod = j
End Function

也适用于小数,区域设置无关紧要。唯一的限制是您可能永远不会遇到的字符串的最大长度。

使用“123456789012345678901234567890.3241543”和 643(即 435.3241543)对其进行了测试。

如果你有任何问题,尽管问;)

【讨论】:

以上是关于函数 MOD 上的 Excel 错误的主要内容,如果未能解决你的问题,请参考以下文章

403 错误禁止您无权访问此服务器 mod_wsgi 和 apache 上的 /myapp

Excel mod函数的使用方法 Excel mod函数的使用步骤

Excel表格中mod函数的使用方法都有哪些

一台虚拟主机上的多个 mod_wsgi 应用程序指向错误的应用程序

安装 mod_wsgi 时如何修复错误消息?

如何在 VBA 中使用 Excel 的内置模函数 (MOD)?