处理数学函数中的错误

2024-01-02

数学相关函数中错误处理的良好做法是什么?我正在构建一个专门函数的库(模块),我的主要目的是使调用这些函数的代码更容易调试——而不是创建一个闪亮的用户友好的错误处理工具。

下面是 VBA 中的一个简单示例,但我也有兴趣听到其他语言的信息。我不太确定应该在哪里返回错误消息/状态/标志。作为额外的论据?

Function AddArrays(arr1, arr2)
    Dim i As Long
    Dim result As Variant

    ' Some error trapping code here, e.g.
    ' - Are input arrays of same size?
    ' - Are input arrays numeric? (can't add strings, objects...)
    ' - Etc.

    ' If no errors found, do the actual work...
    ReDim result(LBound(arr1) To UBound(arr1))
    For i = LBound(arr1) To UBound(arr1)
        result(i) = arr1(i) + arr2(i)
    Next i

    AddArrays = result
End Function

或类似以下内容。该函数返回一个布尔“成功”标志(如下例所示,如果输入数组不是数字等,则返回 False),或其他类型的错误号/消息。

Function AddArrays(arr1, arr2, result) As Boolean

    ' same code as above

    AddArrays = booSuccess

End Function

然而我对此并不太着迷,因为它破坏了良好且可读的调用语法,即不能说c = AddArrays(a,b)不再了。

我愿意接受建议!


显然,错误处理通常是一个大主题,最佳实践在很大程度上取决于您正在使用的语言的功能以及您正在编码的例程如何与其他例程相适应。因此,我将把我的答案限制为 VBA(在 Excel 中使用)和您所描述的那种库类型例程。

库例程中的异常与错误代码

在这种情况下,我会not使用返回码。 VBA 支持一种异常处理形式,虽然不如 C++/Java/??.NET 中更标准的形式强大,但非常相似。因此,这些语言的建议通常适用。您可以使用异常来告诉调用例程,被调用例程由于某种原因无法完成其工作。您可以在最低级别处理异常,在这里您可以对失败做一些有意义的事情。

Bjarne Stroustrup 在本书中很好地解释了为什么在这种情况下异常比错误代码更好。 (这本书是关于 C++ 的,但是 C++ 异常处理和 VBA 错误处理背后的原理是相同的。)

http://www2.research.att.com/~bs/3rd.html http://www2.research.att.com/~bs/3rd.html

以下是第 8.3 节的精彩摘录:

当一个程序由单独的 模块,尤其是当那些 模块来自单独开发 库,错误处理需要 分为两个不同的部分:[1] 错误情况的报告 无法在本地解决 [2] 处理其他地方检测到的错误 库的作者可以检测到 运行时错误,但通常不会 知道该怎么办。 图书馆的用户可能知道如何 处理此类错误但不能 检测到它们——否则它们就会 在用户代码中处理,而不是 留给图书馆去寻找。

第 14.1 节和第 14.9 节还讨论了库上下文中的异常与错误代码。 (archive.org 上有这本书的在线副本。)

stackoverflow 上可能有更多关于此的信息。我刚刚发现这个,例如:

异常、错误代码、断言 https://stackoverflow.com/questions/1388335/exception-vs-error-code-vs-assert/1388482#1388482

(可能存在涉及正确管理资源的陷阱,在使用异常时必须清除这些陷阱,但它们并不真正适用于此。)

VBA 中的异常

以下是在 VBA 中引发异常的方式(尽管 VBA 术语是“引发错误”):

Function AddArrays(arr1, arr2) 
    Dim i As Long 
    Dim result As Variant 

    ' Some error finding code here, e.g. 
    ' - Are input arrays of same size? 
    ' - Are input arrays numeric? (can't add strings, objects...) 
    ' - Etc. 

    'Assume errorsFound is a variable you populated above...
    If errorsFound Then
        Call Err.Raise(SOME_BAD_INPUT_CONSTANT)    'See help about the VBA Err object. (SOME_BAD_INPUT_CONSTANT is something you would have defined.)
    End If

    ' If no errors found, do the actual work... 
    ReDim result(LBound(arr1) To UBound(arr1)) 
    For i = LBound(arr1) To UBound(arr1) 
        result(i) = arr1(i) + arr2(i) 
    Next i 

    AddArrays = result 
End Function

如果此例程没有捕获错误,VBA 将为调用堆栈中位于其上方的其他例程提供机会(请参见以下内容:VBA 错误“冒泡” https://stackoverflow.com/questions/1418777/vba-error-bubble-up/1419147#1419147)。调用者可能会这样做:

Public Function addExcelArrays(a1, a2)
    On Error Goto EH

    addExcelArrays = AddArrays(a1, a2)

    Exit Function

EH:

    'ERR_VBA_TYPE_MISMATCH isn't defined by VBA, but it's value is 13...
    If Err.Number = SOME_BAD_INPUT_CONSTANT Or Err.Number = ERR_VBA_TYPE_MISMATCH Then

        'We expected this might happen every so often...
        addExcelArrays = CVErr(xlErrValue)
    Else

        'We don't know what happened...
        Call debugAlertUnexpectedError()    'This is something you would have defined
    End If
End Function

“做一些有意义的事情”的含义取决于您的应用程序的上下文。在上面的调用者示例中,it决定应通过返回 Excel 可以放入工作表单元格中的错误值来处理某些错误,而其他错误则需要令人讨厌的警报。 (这里的 Excel 中的 VBA 的情况实际上是一个不错的具体示例,因为许多应用程序区分了内部例程和外部例程,以及您期望能够处理的异常和您只想了解的错误条件但您没有对此做出回应。)

不要忘记断言

因为您提到了调试,所以还值得注意断言的作用。如果您希望 AddArrays 只能由实际创建了自己的数组或以其他方式验证它们正在使用数组的例程调用,您可以这样做:

Function AddArrays(arr1, arr2) 
    Dim i As Long 
    Dim result As Variant 

    Debug.Assert IsArray(arr1)
    Debug.Assert IsArray(arr2)

    'rest of code...
End Function

关于断言和异常之间差异的精彩讨论如下:

Debug.Assert 与异常抛出 https://stackoverflow.com/questions/1467568/debug-assert-vs-exception-throwing/1468385#1468385

我在这里举了一个例子:

断言是邪恶的吗? https://stackoverflow.com/questions/1854302/is-assert-evil/1894867#1894867

关于通用数组处理例程的一些 VBA 建议

最后,作为特定于 VBA 的说明,VBA 变体和数组带有许多陷阱,当您尝试编写通用库例程时必须避免这些陷阱。数组可能有多个维度,它们的元素可能是对象或其他数组,它们的开始和结束索引可能是任何东西,等等。下面是一个示例(未经测试且不试图详尽),它解释了其中的一些内容:

'NOTE: This has not been tested and isn't necessarily exhaustive! It's just
'an example!
Function addArrays(arr1, arr2)

    'Note use of some other library functions you might have...
    '* isVect(v) returns True only if v is an array of one and only one
    '  dimension
    '* lengthOfArr(v) returns the size of an array in the first dimension
    '* check(condition, errNum) raises an error with Err.Number = errNum if
    '  condition is False

    'Assert stuff that you assume your caller (which is part of your
    'application) has already done - i.e. you assume the caller created
    'the inputs, or has already dealt with grossly-malformed inputs
    Debug.Assert isVect(arr1)
    Debug.Assert isVect(arr2)
    Debug.Assert lengthOfArr(arr1) = lengthOfArr(arr2)
    Debug.Assert lengthOfArr(arr1) > 0

    'Account for VBA array index flexibility hell...

    ReDim result(1 To lengthOfArr(arr1)) As Double
    Dim indResult As Long

    Dim ind1 As Long
    ind1 = LBound(arr1)

    Dim ind2 As Long
    ind2 = LBound(arr2)

    Dim v1
    Dim v2

    For indResult = 1 To lengthOfArr(arr1)

        'Note implicit coercion of ranges to values. Note that VBA will raise
        'an error if an object with no default property is assigned to a
        'variant.
        v1 = arr1(ind1)
        v2 = arr2(ind2)

        'Raise errors if we have any non-numbers. (Don't count a string
        'with numeric text as a number).
        Call check(IsNumeric(v1) And VarType(v1) <> vbString, xlErrValue)
        Call check(IsNumeric(v2) And VarType(v2) <> vbString, xlErrValue)

        'Now we don't expect this to raise errors.
        result(indResult) = v1 + v2

        ind1 = ind1 + 1
        ind2 = ind2 + 1
    Next indResult

    addArrays = result
End Function
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

处理数学函数中的错误 的相关文章

  • 使用宏打开受信任文档或启用宏时 Excel 崩溃

    正如标题所示 我无法使用宏打开受信任的文档 Excel 立即崩溃 制作文档的副本允许其打开 因为该副本不受信任 并且我可以检查 VB 编辑器中的宏 但启用宏会导致另一次崩溃 为什么会发生这种情况以及我可以采取什么措施来解决它 我今天遇到了类
  • 将名称字符串编码为唯一的数字

    我有一大堆名字 数以百万计 他们每个人都有一个名字 一个可选的中间名和一个姓氏 我需要将这些名称编码为唯一代表这些名称的数字 编码应该是一对一的 即一个名称只能与一个数字相关联 一个数字只能与一个名称相关联 对此进行编码的明智方法是什么 我
  • 批处理文件中是否存在“Power to”功能? (指数)

    Problem 有没有办法将变量 乘以 数字或其他变量的批处理文件 有这个功能吗 Python 中的一个示例是您可以使用 为 到 的力量 EDIT 您可以在批处理文件中进行数学运算 http en wikipedia org wiki Ba
  • 如何隐藏组合框下拉列表中的列?

    我正在 Excel 用户窗体中构建一个 ComboBox 该用户窗体从 Access 表中获取其行 我想在下拉列表中向用户显示多个文本字段 但从 ComboBox 返回的值应该是与用户选择的行关联的 ID 号 即 ID 列是绑定列 但我不想
  • 在用户窗体终止/关闭 VBA 时调用数组

    我有一个问题 我想在用户窗体关闭时将用户窗体的内容存储在数组中 我认为我的语法正确 但似乎不会在用户窗体初始化时重新填充 我尝试将数组放入其自己的模块中 但这也不起作用 有人愿意启发我吗 示例代码 Public Sub DPArrayStu
  • 如何在Python的SciPy中更改稀疏矩阵中的元素?

    我构建了一个小代码 我想用它来解决涉及大型稀疏矩阵的特征值问题 它工作正常 我现在要做的就是将稀疏矩阵中的一些元素设置为零 即最顶行中的元素 对应于实现边界条件 我可以调整下面的列向量 C0 C1 和 C2 来实现这一点 不过我想知道是否有
  • 查找其索引的乘积可被另一个数字 X 整除的对的数​​量

    给定一个数组和某个值 X 找到满足以下条件的对的数量 i lt j a i a j and i j X 0 Array size lt 10 5 我想这个问题有一段时间了 但只能想出蛮力解决方案 通过检查所有对 这显然会超时 O N 2 t
  • 将 CURL 命令行转换为 VBA

    在 CURL 中 我可以使用这一行 curl data DataToBeSent https example com resource cgi 我正在努力将此类行转换为在 VBA 中使用 这是我到目前为止的尝试 Sub POST Metho
  • 是什么导致 Java(冰雹序列)在我的程序中崩溃

    我制作了一个执行 通常称为 冰雹序列的程序 该程序基本上执行以下操作 创建一个int 值 并为其分配一个值 如果 int 是偶数 则将其除以二 如果 int 为奇数 则将其乘以三并加一 继续这个过程 直到 n 等于 1 它似乎适用于大多数数
  • 如何使用Excel的墨迹工具添加手写签名?

    我想在我公司的一些表格中添加手写数字签名 目标是选择一个文档 添加签名 通过使用绘图板 这可以使用 Excel 的墨水工具完成 并将文件作为 PDF 存储在服务器中 这将消除打印然后扫描表格以获得签名的必要性 我使用 Excel 作为文件操
  • VBA 中的 If 和 Or 多个语句

    我想将包含 14 列的 Excel 文件重新分配到正确的列 包含 12 000 行 为此 我必须使用一些 If And Or 语句将数字放入矩阵中 但显然我没有从中得到正确的东西 它使我的所有单元格为零 而具有值的单元格应保留该值 我哪里出
  • 如何从矩形点计算旋转角度?

    我有4分1 2 3 4闭合一个矩形 这些点按以下方式排列在数组中 x1 y1 x2 y2 x3 y3 x4 y4 我遇到的问题是矩形可以旋转一定角度 如何计算原始点 灰色轮廓 和角度 我试图在 javascript css3 transfo
  • VBA复制单元格值和格式

    我如何修改以下代码以便不仅复制值而且复制字体样式 例如大胆或不大胆 谢谢 Private Sub CommandButton1 Click Dim i As Integer Dim a As Integer a 15 For i 11 To
  • 根据单元格值返回图像(100 张图像和可变单元格)

    我正在尝试为我制作一个 TFT 云顶之弈 表 并想让它看起来更好 为此 我想添加游戏中冠军的图像 当我输入名称时 图像应该出现在下面 我找到了一种将所有图像插入 Excel 工作表 100 的方法 并且还成功制作了一个动态图像 插入 IND
  • VBA - 如何从网站下载.xls并将数据放入Excel文件

    我设法使用 VBA 达到准备从网络下载 Excel 文件的程度 但我无法弄清楚如何实际下载该文件并将其内容放入我正在使用的 Excel 文件中 有什么建议么 谢谢 这是到目前为止的代码 Sub GetData Dim IE As Inter
  • 两个数组相乘 - 区域小数分隔符问题

    Background 刚才 我回答了一个问题 我必须将两个相同大小的数组相乘 但是我注意到我的本地小数分隔符存在一个特殊问题 Sample Code Sub Sample Dim arr1 As Variant arr2 As Varian
  • 如果不是,则必须删除单元格的第一个字符 #3Created 循环永远不会结束

    所以基本上 我需要删除主键字段中第二位数字不为 3 的所有记录 例如可以如下所示 39001 或者没有 3 我想要的是所有以非 3 开头的单元格 它们的行都被删除我想出了以下代码 它删除了所有单元格 但宏永远不会停止运行 Sub keep3
  • 从 Excel 数据为列中的每个不同值创建 CSV 文件?

    我有一个 Excel 其供应商代码 数字 作为其中一列 VENDORITEM DESCRIPTION PRICE PRICEGROUP VENDOR NUMBER PRODUCT CATEGORY HNM36789 30ML FLUID C
  • Excel VBA - 以编程方式列出用户窗体上控件的可用事件过程

    你好 我已经搜索过 google 但发现只有 1 页提到了如何在 MS Access 中执行此操作 但没有在 MS Excel 中执行此操作 此处 列出 MS Access 表单的控件及其事件 https stackoverflow com
  • 复制数据透视表格式

    我无法将数据透视表格式复制到新工作表 基本上我想做的是 someRange Copy someOtherRange pasteSpecial xlPasteValues someOtherRange pasteSpecial xlPaste

随机推荐

  • Spring Cloud Gateway - 修改全局后置过滤器中的响应正文

    在过去的两天里 我在请求到达客户端之前尝试了各种可能的方法来修改请求的响应正文 但似乎没有任何方法对我有用 到目前为止我已经尝试过提到的实现here https gist github com dalegaspi 03550807b1c84
  • 如何使用 Java 脚本从 Android 移动浏览器获取序列号,该脚本来自移动浏览器中运行的 Web 应用程序源 [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我可以从 Android 手机找到 UniqueId 序列号 IMEI 操作系统和 IP 地址 本机应用程序 但是 我无法通过移动浏览器应用
  • 包装模板函数和<未解析的重载函数类型

    我的包装功能有问题 template
  • 给定两个数组,找到给出两个数组之间最接近距离的排列

    假设我有两个长度相同的数组n named A and B 这两个数组包含实数值 我们将两个数组之间的距离定义为均方距离 dist A B sqrt sum A B 2 我想找到的排列A这给出了最小距离B 最简单的方法是尝试每一个排列A并记录
  • Python3 tkinter设置图像大小

    我到处寻找一种设置图像大小的方法 图像被设置为 url 我在网站上发现了其他问题 但没有一个有效 import urllib request base64 u urllib request urlopen currentWeatherIco
  • 如何修改另一个函数收到的 XMLHttpRequest 响应文本?

    我正在尝试修改我无法修改的函数收到的responseText 该函数创建了一个我可以附加到的 XMLHttpRequest 但我无法以允许我在原始函数接收之前修改内容的方式 包装 responseText 这是完整的原始函数 functio
  • 为什么在 C 中将枚举元素分配给相同的枚举变量类型时必须对其进行强制转换?

    我有以下内容 typedef enum FLS PROG SUCCESS FLS PROG FAIL FLS ERASE SUCCESS2U FLS ERASE FAIL FLS READ SUCCESS FLS READ FAIL FLS
  • 使用 vbscript 自动实现页面滚动

    我需要使用 vbscript 拍摄页面的完整快照 为此我需要向下滚动一点 实际上 我可以在快照中拍摄页面的一半 但我还需要在下一个快照中拍摄剩余部分 页面加载后我尝试使用以下内容 ie document body doScroll page
  • MySQL 中的更改数据捕获

    在我的数据库中 我想在每次更改列的值时跟踪它 以某种方式 每次字段值更改时我们都可以知道以前的值是什么 为每次更改分配时间戳会很棒 我我使用 MySQL 作为数据库服务器 我建议你看一下Debezium http debezium io 一
  • 如何将 Visual Studio 2017.3 降级到 2017.2?

    将 VS 更新到 2017 3 破坏了我的 xunit 测试发现 2017 2 一切正常 所以我正在寻找降级的方法 无法直接降级 但可以安装特定版本 使用 Visual Studio 安装程序卸载 Visual Studio 2017 从以
  • 我的组织用户对 Azure Devops 存储库的访问受到限制

    我们最近将代码移到了 azure devops 上 我们在 azure AD 中创建了用户帐户 并将相同的用户添加到 Azure Devops 中 以便他们可以访问代码 现在我们希望限制对存储库的访问 我检查了这个网址 Azure DevO
  • Firebase 云消息传递是否符合 HIPAA?

    我想在医疗保健应用程序中使用 Firebase Cloud Messaging 我想知道 FCM 是否符合 HIPAA 标准并且是否提供 BAA 我们刚刚与第三方完成了使用端到端加密的 Firestore Chat 示例应用程序 iOS 和
  • Win32 No-MFC 中的消息映射

    我如何创建类似的结构来处理 Win32 消息 就像在 MFC 中一样 In MFC BEGIN MESSAGE MAP CSkinCtrlTestDlg CDialog AFX MSG MAP CSkinCtrlTestDlg ON BN
  • 有 Ruby 语法的权威参考文档吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找有关 Ruby 语法的权威文档 我知道核心 API 和标准库的权威文档 但是语法本身呢 例如
  • 如何从左侧而不是顶部滑动导航栏?

    Bootstrap 支持从顶部切换导航栏 屏幕较小时如何从左侧滑动 例如 在上面提供的屏幕截图中 当调整屏幕大小时 导航栏会切换并从顶部向下滑动 我宁愿希望导航栏从左侧滑动 在Bootstrap中如何实现这个功能呢 目前 根据代码 导航栏从
  • Keycloak 模板可用变量

    我在谷歌上搜索了一段时间 以便找到我可以在各种 Keycloak 模板中使用的所有可用的 变量 的文档 我所说的变量是指所有的 xxx yyy 我可以用它来在模板中注入一些动态值 通过文档我可以在这里和那里找到其中的一些 例如 user a
  • cypress - 访问主站点时出现 403 禁止错误

    我正在尝试 cy visit 我的单页应用程序 该应用程序需要在浏览器中加载我的证书才能正确运行 运行测试时 它失败并出现 403 禁止错误 有一个可怕的解决方法 我在 cypress chrome 浏览器窗口中打开一个新选项卡 然后直接转
  • C++ 中指针“this+1”指的是什么?

    我正在浏览代码G2P 推理 https www i6 informatik rwth aachen de web Software g2p html并发现了一行非常奇怪的代码 public const Node childrenEnd co
  • 按服务数据 UUID 进行 BLE 扫描过滤器

    我们有使用 服务数据 128 位 UUID AD 类型信标数据的设备 0x21 对于 Android 扫描 我们通过 MAC 地址过滤 BLE 设备 效果很好 因为我们需要更大的灵活性 所以我们想通过 UUID 进行过滤 我的代码仅适用于小
  • 处理数学函数中的错误

    数学相关函数中错误处理的良好做法是什么 我正在构建一个专门函数的库 模块 我的主要目的是使调用这些函数的代码更容易调试 而不是创建一个闪亮的用户友好的错误处理工具 下面是 VBA 中的一个简单示例 但我也有兴趣听到其他语言的信息 我不太确定