2015-04-04 3 views
0

Je suis en train de créer une méthode de conversion d'un nombre en notation scientifique normalisée, voici le code que j'utilise pour calculer mantisse et exposant:Convertir un nombre en notation scientifique normalisée

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 

Le problème Je fais face est que ce code donne une fausse valeur d'exposant pour certains nombres, par exemple 1000, 10E + 6, 10E + 9, 10E + 12, 10E + 13, etc ... Exactement pour 1000 converti devrait être 1e3, mais pas 10e2. Il est évident que le même problème avec les nombres, dont les logarithmes sont proches d'une valeur entière, comme Log(1 - 5.55111512312578E-17)/Log(10), qui résulte est 0, mais 1 - 5.55111512312578E-17 moins de 1, et le résultat doit être négatif.

Comment puis-je me débarrasser de Double Imprécision type et obtenir ce code fonctionne correctement?

MISE À JOUR

Je suppose que la méthode la plus rapide et tout à fait exact de calculer mantisse et exposant du nombre en notation scientifique normalisée peut être la suivante:

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 

Ou un autre, basé sur @ Bob solution:

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 

Première légèrement plus rapide. Les deux traitent l'exposant de -322 à 308, mais retournent une mantisse non normalisée avec des puissances de 10 inférieures à -310. Je ne les ai pas encore testés avec des nombres, dont les logarithmes sont un peu plus faibles mais très proches des valeurs entières.

MISE À JOUR 2

j'ai décidé de joindre ici un Sub ConvEN() supplémentaire, ce qui permet de représenter un nombre en notation d'ingénierie avec des préfixes SI de "p" à "T":

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 

Répondre

0

Try this :

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

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

ConvNSN -0.000000000000000, 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 

Basé sur les commentaires, j'ai réécrit ceci à ma façon, en ignorant la structure de l'OP.

MsgBox NSN(-0.000000000000000000,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 
+0

Que se passerait-il si 'M> = 1 et M <= 10'? Essayez 'ConvNSN 5, M, P' – JosefZ

+0

Les nombres compris entre 1 et 10 ne sont généralement pas écrits en notation scientifique. La notation scientifique est la façon dont les scientifiques manipulent facilement de très grands nombres ou de très petits nombres. – Bob

+0

Semble 'Round()' pourrait être utile. J'ai noté 'NSN (1e-14, 15)' renvoie '10E-13'. La seule façon d'obtenir un résultat correct est de couper les derniers chiffres, donc 'NSN (1e-14, 14)' retourne '1E-14'. Il s'adapte si la haute précision n'est pas nécessaire (comme pour afficher les valeurs), puisque la machine epsilon pour 'Double' est' 1.11e-16'. J'ai aussi essayé 'ConvNSN 1000, M, P: MsgBox M &" E "& P', et il me donne toujours' 10E2' pour moi. – omegastripes

0

L'utilisation de chaînes plutôt que de maths peut aider. Ajoutez votre propre vérification d'erreur.

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)