将数字转换为标准化的科学记数法

时间:2015-04-04 23:09:39

标签: vbscript wsh double-precision scientific-notation

我正在尝试创建一个将数字转换为规范化科学记数法的方法,这里是我用来计算尾数和指数的代码:

ConvNSN 1000, M, P
MsgBox M & "e" & P

Sub ConvNSN(N, M, P)
    If N = 0 Then
        P = 0
        M = 0
    Else
        P = Int(Log(Abs(N)) / Log(10))
        M = N / 10 ^ P
    End If
End Sub

我面临的问题是这段代码为某些数字提供了错误的指数值,例如1000,10E + 6,10E + 9,10E + 12,10E + 13等......正好适用于1000转换应为1e3 ,但不是10e2。很明显,数字的相同问题,其对数接近整数值,如Log(1 - 5.55111512312578E-17) / Log(10),结果为0,但1 - 5.55111512312578E-17小于1,结果必须为负。

如何摆脱Double类型的不精确,并使此代码正常工作?

更新

我假设用标准化科学计数法计算尾数和数字指数的最快且非常准确的方法可能如下:

Sub ConvNSN(N, M, P)
    Dim A
    If N = 0 Then
        P = 0
        M = 0
        Exit Sub
    End If
    A = Abs(N)
    If A < 1 Then
        P = Int(Log(A) / Log(10))
    Else
        P = Int(Log(A) / Log(10) * (2 + Log(.1) / Log(10)))
    End If
    M = N / 10 ^ P
End Sub

或另一个,基于@ Bob的解决方案:

Sub ConvNSN(N, M, P)
    If N = 0 Then
        P = 0
        M = 0
    Else
        P = Int(Log(Abs(N)) / Log(10))
        M = N / 10 ^ P
    End If
    If Abs(M) = "10" Then
        M = M / 10
        P = P + 1
    End If
End Sub

第一个稍快一点。它们都处理从-322到308的指数,但是返回未标准化的尾数,其幂10小于-310。我还没有用数字测试它们,它们的对数略小但非常接近整数值。

更新2

我决定在这附加一个额外的Sub ConvEN(),允许用工程符号表示一个带有“p”到“T”的SI前缀的数字:

N = .0000456789
ConvNSN N, M, P
M = Round(M, 2)
ConvEN M, P, R, S
MsgBox R & " " & S & "Units"

Sub ConvNSN(N, M, P)
    Dim A
    If N = 0 Then
        P = 0
        M = 0
        Exit Sub
    End If
    A = Abs(N)
    If A < 1 Then
        P = Int(Log(A) / Log(10))
    Else
        P = Int(Log(A) / Log(10) * (2 + Log(.1) / Log(10)))
    End If
    M = N / 10 ^ P
End Sub

Sub ConvEN(M, P, R, S)
    DIM Q, P3
    Q = int(P / 3)
    P3 = Q * 3
    If Q >= -4 And Q <= 4 Then
        S = Array("p", "n", ChrW(&H03BC), "m", "", "k", "M", "G", "T")(Q + 4)
    Else
        S = "e" & P3 & " "
    End If
    R = M * 10 ^ (P - P3)
End Sub

2 个答案:

答案 0 :(得分:0)

试试这个:

ConvNSN 1000, M, P
MsgBox M & "E" & P

ConvNSN 0.00000000000000001234, M, P
MsgBox M & "E" & P

ConvNSN -0.00000000000000001234, M, P
MsgBox M & "E" & P

Sub ConvNSN(N, M, P)
  P = 0
  If N < 0 Then
    S = -1
  ElseIf N > 0 Then
    S = 1
  Else
    M = 0
    Exit Sub
  End If
  M = Abs(N)
  If M >= 10 Then
    While M >= 10
      M = M / 10
      P = P + 1
    Wend
    M = M * S
    Exit Sub
  End If
  If M < 1 Then
    While M < 1
      M = M * 10
      P = P - 1
    Wend
    M = M * S
    Exit Sub
  End If
End Sub

根据评论,我以自己的方式重写了这一点,忽略了OP的结构。

MsgBox NSN(-0.0000000000000000000123456789,4)
MsgBox NSN(1234567890000000000000000000,4)

Function NSN(Number, Accuracy)
  Exponent = 0
  If Number > 0 Then
    Sign = 1
  ElseIf Number < 0 Then
    Sign = -1
  Else
    NSN = 0
    Exit Function
  End If
  Number = Number * Sign
  If Number >= 10 Then
    While Number >= 10
      Number = Number / 10
      Exponent = Exponent + 1
    Wend
  ElseIf Number < 1 Then
    While Number < 1
      Number = Number * 10
      Exponent = Exponent - 1
    Wend
  End If
  Number = Round(Number, Accuracy)
  If Number = "10" Then
    Number = 1
    Exponent = Exponent + 1
  End If
  Number = Number * Sign
  If Exponent = 0 Then
    NSN = Number
  Else
    NSN = Number & "E" & Exponent
  End If
End Function

答案 1 :(得分:0)

使用字符串而不是数学可以提供帮助。添加自己的错误检查。

Num = "1000000.0005"
NumOfDigits = 4

Mag = Instr(Num, ".")
Num = Replace(Num, ".", "")
MSD = Left(Num, 1)
Rest = Mid(num, 2, NumOfDigits)


msgbox MSD & "." & Rest & " x 10^" & (Mag -2)