【问题标题】:How to round to a certain number of significant figures using Excel VBA?如何使用 Excel VBA 四舍五入到一定数量的有效数字?
【发布时间】:2012-07-31 14:58:55
【问题描述】:

编辑:这部分解决了!

所以我在我正在制作的程序中有一堆计算,并且数字变得太长以至于我得到溢出错误。它是由一个 50 位数字除以另一个 50 位数字之类的结果产生的。我需要一种方法将特定数字四舍五入到一定数量的有效数字。

这里有更多信息。首先,我将四舍五入的所有数字将始终小于 1。数字可以小到 1E-50。我只关心前 10 位左右的有效数字。在继续下一个计算之前,我只需要一种方法将其四舍五入到大约 10 sig figs,以防止溢出错误。那个,而且有一个数字达到 50 个数字是非常没用的。

我在考虑可能逐个数字地循环遍历数字?当数字等于 0 时,该程序可以将 1 加到计数器上,然后在遇到除零以外的任何值时跳出循环。然后下一步可以将数字截断到该计数器加上我想要的许多有效数字。

以 .000001234567812345678 为例。它将返回 5 个零。如果我想要十位有效数字,我会做五 + 十 = 15。然后程序将只保留小数点后的前 15 位数字,因此该数字将被截断为 .000001234567812。

另一个想法可能是使用日志。那么新数字的幂将是有效数字前零的数量。

我不知道的是,首先,如何逐位遍历一个数字,并检查每个数字是否为零。我也不知道如何将数字截断为一定数量的数字。

任何帮助将不胜感激!

编辑:这部分没有解决。

这么快再发一个帖子我会感觉很糟糕,所以我要在这里问这个问题。如果20分钟左右没有回复,也许我会再发一个帖子。为什么这不起作用?

Sub Rounding()
    Tracker = 0
    For i = 1 To 10
        Tracker = Tracker + 1
        Cells(1, Tracker) = Rnd
        Cells(1, Tracker) = Application.Evaluate("=Round(Cells(1, Tracker), 4 - (Int(Log(Cells(1,Tracker))) + 1))")
    Next
    Columns("A:J").EntireColumn.AutoFit
End Sub

我在每个单元格中都不断收到错误 #NAME?。这应该将每个数字四舍五入到四位有效数字。

【问题讨论】:

  • 值得指出的是,Excel 只能使用 15 位精度:您的 50 位数字不能“正确”表示。在此处查看 Jerry 的答案:excelforum.com/excel-general/…

标签: vba excel excel-2010


【解决方案1】:

假设您的值在 A2 中,请尝试以下任一方法:

=ROUND(A2, 3-(INT(LOG(A2))+1))

或

=ROUND(A2,3-LEN(INT(A2)))

取自here。

【讨论】:

  • 这很好用!所以红色的数字是我想要多少个有效数字。我将如何在 VBA 中实际使用它?我试过Range("A4") = Application.Worksheetfunction.Round(A2,3-(Int(Log(A2))+1)),但没有用。我不断收到“无效的过程调用或参数”。
  • 试试Range("A2") 而不是A2。
  • 我把它改成了Range("A4") = Application.Evaluate("=Round(A2,3-(Int(Log(A2))+1))"),它成功了!它确实将最后一个数字四舍五入,但我可以添加一个额外的数字,这无关紧要。谢谢!
  • 你知道为什么我用这个制作的程序不起作用吗?我把它放在上面的文字中,在我原来的问题下面。
  • @TheTreeMan - 对不起,我在吃午饭 :) Siddharth Rout 的回答看起来是正确的。
【解决方案2】:

既然已经有一个函数可以满足你的需求,为什么还要循环呢?

Sub Sample()
    Dim someNumber As Double

    '~~> .000001234567812345678
    someNumber = 1.23456781234568E-06

    '~~> This will give you .000001234567812
    Debug.Print Round(someNumber, 15)
End Sub

【讨论】:

  • 每次都不会有相同数量的零。它的范围可以从无零到五十个零。我可以使用 Round() 函数,但我需要一种方法来检测有多少个零,所以我知道要将它四舍五入到多少位。
  • 使用 LittleBobbyTables 的方法,我得到了程序的工作!但是,在编辑程序以在填充单元格时移动并应用于单元格后,程序“崩溃”了。我把有问题的代码放在上面,在我遇到的另一个问题下面。为什么它总是给我一个#NAME?错误?是因为里面的 Cells() 引用吗?它在我正在测试的一个模块中工作,用于单个单元格,直到我将其更改为与跟踪器一起移动。
  • 将Cells(1, Tracker) = Application.Evaluate("=Round(Cells(1, Tracker), 4 - (Int(Log(Cells(1,Tracker))) + 1))") 更改为Cells(1, Tracker) = Application.Evaluate("=Round(Cells(1," & Tracker & "), 4 - (Int(Log(Cells(1," & Tracker & "))) + 1))") Tracker 是一个变量,而不是一个字符串;)
  • 啊,真是个愚蠢的错误!谢谢你。编辑:它实际上给了我同样的错误?
  • 我把它放到了 Excel 中,并稍微修改了一下,使它不再依赖于跟踪器,只是为了看看它是否有效,然后我得到了 #NAME?每个单元格中的错误。我输入了=ROUND(Cells(1,1), 4 - (INT(LOG(Cells(1,1))) + 1))。如果我单击错误,则会显示“此公式包含无法识别的文本”。
【解决方案3】:

我发现在 excel 工作表中,可以使用: =ROUND(A2, 3-(INT(LOG(A2))+1))

但在 VBA 中,代码变为: =Round(Range("A2"), 3-(Int(Log(Range("A2"))/log(10#))+1))

【讨论】:

    【解决方案4】:

    如果 3-(Int(Log(Range("A2"))/log(10#))+1)) 为负数(即小数点前的有效数字比您希望的多),这将不起作用将数字四舍五入)。另一种选择是

    Public Function round_sigfig(ByVal myval As Double, ByVal fignum As Integer) As Double
    factor = 10 ^ (fignum - (Int(Log(myval) / Log(10#))) - 1)
    round_sigfig = Round(myval * factor, 0) / factor
    End Function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-17
      • 2013-04-07
      • 1970-01-01
      • 2016-11-24
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 2011-01-22
      相关资源
      最近更新 更多