【发布时间】:2015-04-04 23:09:38
【问题描述】:
我正在尝试创建一种将数字转换为标准化科学记数法的方法,这是我用来计算尾数和指数的代码:
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 的指数,但返回未归一化的尾数,其幂小于 -310 的 10。我还没有用数字对它们进行测试,它们的对数略小但非常接近整数值。
更新 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
【问题讨论】:
标签: vbscript wsh double-precision scientific-notation