如何使用Excel VBA四舍五入到一定数量的有效数字?

zpqajqem  于 2023-05-01  发布在  其他
关注(0)|答案(6)|浏览(209)

编辑:此部分已解决!

所以我在一个程序里做了一大堆的计算,这些数字变得太长了,以至于我得到了溢出错误。它是由一个50位数除以另一个50位数得到的。我需要一种方法将特定的数字四舍五入到一定数量的有效数字。
这里有更多的信息。首先,我将舍入的所有数字将始终小于1。这些数字可以小到1 E-50。我只关心前10位左右的有效数字。我只需要一种方法来四舍五入到大约十个sig图,然后再进行下一个计算,以防止溢出错误。这一点,并有一个数字出去50位数是非常无用的。
我在想,也许循环通过数字,一位一位?程序可以在计数器等于零时将1加到计数器上,然后一旦计数器达到除零以外的任何值,就中断循环。然后,下一步可以截断该计数器的数字,加上我想要的任何有效数字。
例如,000001234567812345678。它将返回5个零。如果我想要10个有效数字,我会做5 + 10 = 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?,在每一个细胞中。这应该将每个数字四舍五入为四位有效数字。

qmelpv7a

qmelpv7a1#

假设你的值在A2中,尝试以下任一项:

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

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

来自here

3htmauhk

3htmauhk2#

当已经有一个函数给你想要的东西时,你为什么要循环?

Sub Sample()
    Dim someNumber As Double

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

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

g9icjywg3#

我发现在Excel工作表中,可以用途:=ROUND(A2,3-(INT(LOG(A2))+1))
但在VBA中,代码变为:=Round(Range(“A2”),3-(Int(Log(Range(“A2”))/log(10#))+1))

oxosxuxt

oxosxuxt4#

如果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
8wigbo56

8wigbo565#

函数roundSignifx舍入为sd有效位。适用于所有数字(x < 1以及x >= 1,也适用于所有负数和0

' Round `x` to `sd` significant digits
Function roundSignif(x As Double, sd As Integer) As Double
    Dim oom As Integer
    Dim d As Integer
    
    oom = orderOfMag(x)
    d = -oom + sd - 1
    
    If d >= 0 Then
        roundSignif = Round(x, d)
    Else
        ' rounding to a negative number of digits is not possible
        roundSignif = Round(x * 10 ^ d, 0) / 10 ^ d
    End If
End Function

' Return order of magnitude of `x`
Function orderOfMag(x As Double) As Integer
    If x = 0 Then
        orderOfMag = 0
    ElseIf Abs(x) < 1 Then
        orderOfMag = WorksheetFunction.RoundUp(WorksheetFunction.Log10(Abs(x)), 0)
    Else
        orderOfMag = WorksheetFunction.RoundDown(WorksheetFunction.Log10(Abs(x)), 0)
    End If
End Function

测试...

Sub testRoundSignif()
    Dim x As Variant
    For Each x In Array(0, 1, 11, 111, -111, 0.0987, -0.123)
        Debug.Print (x & " -> " & roundSignif(CDbl(x), 2))
    Next x
End Sub

0 -> 0
1 -> 1
11 -> 11
111 -> 110
-111 -> -110
0.0987 -> 0.099
-0.123 -> -0.12
dphi5xsq

dphi5xsq6#

未使用WorksheetFunction的版本用于与其他vba平台的可移植性测试:101.538=1016,10.1254=10。13,3.64589=3。646,2.1=2.1,35845。65=35850,-25。438 = -25.44,-15687。354 = -1569,-100= -100,84354。34=84360

Sub test()
    Dim testStr As String
    Dim num, testNum As Variant
    
    testStr = "101.538, 10.1254, 3.64589, 2.1, 35845.65, -25.438, -15687.354, -100, 84354.34"
    testNum = Split(testStr, ",")
    
    For Each num In testNum
        Debug.Print roundupSignifDigits(num, 4)
    Next num
End Sub

Function roundupSignifDigits(inputNum, signifDigits As Integer)

    'rounds up the inputNum to number of significant Digits
    'Example Usage -> Debug.Print roundupSignifDigits(num, 4)
    
    Dim flag, i, NegFact As Integer
    Dim mult  As Double
    
    'If inputNum is negative then take absolute value and then multiply answer at end by NegFact to make it negative again
    If inputNum < 0 Then
        NegFact = -1
        inputNum = Abs(inputNum)
        Else: NegFact = 1
    End If
    
    mult = 10 ^ (signifDigits - 1)
    
    'first check if number is greater than 1 or less than 1
    If inputNum > 1 Then flag = 1 Else flag = 0
    
    Select Case flag
        Case 1
            Do
                i = i + 1
            Loop Until inputNum / 10 ^ i < 1
            inputNum = inputNum / 10 ^ (i - 1)
            roundupSignifDigits = NegFact * Int(inputNum * -mult) / -mult * 10 ^ (i - 1)
    
        Case 0
            Do
                i = i - 1
            Loop Until inputNum / 10 ^ i > 1
            inputNum = inputNum / 10 ^ i
            roundupSignifDigits = NegFact * Int(inputNum * -mult) / -mult * 10 ^ i
    End Select

End Function

相关问题