PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : formatierte Single-Ausgabe



BoGe-Ro
20.10.2010, 10:42
Hallo Forum,

zur übersichtlichen Zahlenausgabe auf LCD und über UART habe ich mir eine Funtion programmiert, welche mir einen Single-Wert in einen String umwandelt, unter Beachtung von Rundung sowie der Vorgabe der Anzahl der Vorkomma- und Nachkommastellen.



$regfile = "m128def.dat"
$crystal = 16000000
$framesize = 120
$swstack = 120
$hwstack = 120
$baud = 57600
$sim

Declare Function Ausgabe(byval _x As Single , Byval _v As Byte , Byval _n As Byte) As String


Dim Ausgabe_string As String * 20
Dim Ausgabe_string_zeichen(21) As Byte At Ausgabe_string Overlay
Dim Zahl As Single : Zahl = -0.2
Dim Restzeit As Long : Restzeit = 0

Do
Zahl = Zahl + 0.1
Print Ausgabe(zahl , 3 , 3)
Loop
End



Function Ausgabe(byval _x As Single , _v As Byte , _n As Byte) As String
'_v = Anzahl Vorkommastellen ; _n = Anzahl Nachkommastellen
Local _string As String * 15 : _string = ""
Local _laenge As Byte
Local _zaehler As Byte : _zaehler = 0
Local _faktor As Long : _faktor = 1
Local _nachkomma_string As String * 10
Local _vorkomma_string As String * 10
Local _anz_zeichen As Byte
Local _minus As Byte

While _zaehler <> _n
_faktor = _faktor * 10
Incr _zaehler
Wend
_x = _x * _faktor
_x = Round(_x)

If _x >= 0 Then 'bei x=0 springt der Simulator in Else-Zweig
_minus = 0
Else
_minus = 1
_x = Abs(_x)
End If

Ausgabe_string = Str(_x)
_laenge = Len(ausgabe_string)
_laenge = _laenge - 2
Ausgabe_string = Left(ausgabe_string , _laenge) '".0" abschneiden

If Ausgabe_string <> "0" Then _nachkomma_string = Right(ausgabe_string , _n) Else _nachkomma_string = "0"

_anz_zeichen = _v + _n
While _laenge < _anz_zeichen
Ausgabe_string = "0" + Ausgabe_string
_laenge = Len(ausgabe_string)
Wend

_vorkomma_string = Left(ausgabe_string , _v)

If _minus = 1 Then _string = "-" Else _string = " "
_string = _string + _vorkomma_string
_string = _string + ","
_string = _string + _nachkomma_string

Ausgabe = _string
End Function




Funktionieren tut es im Simulator - jedoch wird die 0 als Wert nicht erkannt.
Ich habe die Stelle kommentiert - es wird laut Simulator in den Else-Zweig gesprungen, was dann zur Folge hat, dass mir -0 ausgegeben wird.

Ich hab mir ziemlich schwer getan mit dieser Funktion - hat vielleicht jemand eine bessere, schnellere, ressourcenschonendere?

besten Dank


BoGe-Ro

PicNick
20.10.2010, 18:35
mit direkten = Vergleichen ist es bei singles + floats so eine Sache.
Lass dir im Simualtor die x-variable als Hex ausgeben. Ob denn auch wirklich NULL drinsteht.

du kannst dein "If" testen, indem du mal definitv 0.0 in das Single schreibst. das sollte ja schon gehen.

Ich persönlich würde x von Bascom erst ganz normal in einen String umwandeln lassen, und dann zur Formatierung in diesem String rumwerken.

peterfido
20.10.2010, 20:40
Was stört dich an dem FUSING Befehl?

BoGe-Ro
21.10.2010, 07:00
Hallo,

ursprünglich wollte ich auch eine Lösung mit FUSING erreichen.
die gefundenen Nachteile dabei waren:
- Dezimalpunkt statt Komma
- da der Fusing-Befehl wohl keine String-Variable als Maske akzeptiert, muss für jede Anzahl von Nachkommastellen eine IF-Abfrage, bzw. Case-Auswahl entstehen und ein extra Fusing-Befehl geschrieben werden
- die Anzahl der Stellen vor dem Komma beeinflusst der Fusing-Befehl gar nicht


Gruß

BoGe-Ro

PicNick
21.10.2010, 08:35
Ich hab' deiner Function ein paar printout's eingefügt. Du siehst, dass auch nach dem round ein -0.0 rauskommt.
(der Simulator besch..t dich da)


While _zaehler <> _n
_faktor = _faktor * 10
Incr _zaehler
Wend
Print "IN:" ; _x ; "->";
_x = _x * _faktor
Print "*fak:" ; _x ; "->";
_x = Round(_x)
Print "rounded:" ; _x

PicNick
21.10.2010, 09:45
Du kannst nach den faktor-erweitern und vor der <= 0 abfrage eine Abfrage einfügen, ob die Zahl überhaupt <> 0 ist, egal ob + oder -

und dann auf definitiv +0.0 setzen



While _zaehler <> _n
_faktor = _faktor * 10
Incr _zaehler
Wend
_x = _x * _faktor

If _x < 1.0 And _x > -1.0 Then ' -1.0 < _x < +1.0
_x = 0.0
End If

If _x >= 0 Then
_minus = 0
Else
_minus = 1
_x = Abs(_x)
End If

_x = Round(_x)

If Ausgabe_string <> "0" Then _nachkomma_string = Right(ausgabe_string , _n) Else _nachkomma_string = "0"

----etc----

BoGe-Ro
21.10.2010, 10:05
jo, habs gerade mal durchsimuliert...

Simulator hat in den Locals eine glatte 0, gibt aber selber eine -0.0 als Printout aus.

ist irgendwie nicht konsistent....

jedenfalls lässt sich auf diese -0.0 checken - zumindest solang nichts an dieser Round-Funktion verändert wird.

Ein weiterer Fehler war ausserdem noch drin - wenn der Nachkommastring kleiner war, also der Nachkomma-Anteil ursprünglich führende Nullen hatte.

Ist jetzt gefixt und sieht so aus:



$regfile = "m128def.dat"
$crystal = 16000000
$framesize = 120
$swstack = 120
$hwstack = 120
$baud = 57600
$sim

Declare Function Ausgabe(byval _x As Single , Byval _v As Byte , Byval _n As Byte) As String

Dim Ausgabe_string As String * 20
Dim Ausgabe_string_zeichen(21) As Byte At Ausgabe_string Overlay
Dim Zahl As Single : Zahl = -1

Do
Print Zahl ; " rund " ; Ausgabe(zahl , 2 , 1)
Zahl = Zahl + 0.01
Loop
End





Function Ausgabe(byval _x As Single , _v As Byte , _n As Byte) As String
'_v = Anzahl Vorkommastellen ; _n = Anzahl Nachkommastellen
Local _string As String * 15 : _string = ""
Local _laenge As Byte
Local _zaehler As Byte : _zaehler = 0
Local _faktor As Long : _faktor = 1
Local _nachkomma_string As String * 10
Local _vorkomma_string As String * 10
Local _anz_zeichen As Byte
Local _minus As Byte

While _zaehler <> _n
_faktor = _faktor * 10
Incr _zaehler
Wend
'Print "IN:" ; _x ; "->";
_x = _x * _faktor
'Print "*fak:" ; _x ; "->";
_x = Round(_x)
'Print "rounded:" ; _x

If _x >= 0 Or _x = -0.0 Then 'bei x=0 springt der Simulator in Else-Zweig
_minus = 0
Else
_minus = 1
End If
_x = Abs(_x)

Ausgabe_string = Str(_x)
_laenge = Len(ausgabe_string)
_laenge = _laenge - 2
Ausgabe_string = Left(ausgabe_string , _laenge) '".0" abschneiden

_laenge = Len(ausgabe_string)
_anz_zeichen = _n
While _laenge < _anz_zeichen
Ausgabe_string = "0" + Ausgabe_string
_laenge = Len(ausgabe_string)
Wend
_nachkomma_string = Right(ausgabe_string , _n)

_anz_zeichen = _v + _n
While _laenge < _anz_zeichen
Ausgabe_string = "0" + Ausgabe_string
_laenge = Len(ausgabe_string)
Wend

_vorkomma_string = Left(ausgabe_string , _v)

If _minus = 1 Then _string = "-" Else _string = " "
_string = _string + _vorkomma_string
If _n > 0 Then
_string = _string + ","
_string = _string + _nachkomma_string
End If

Ausgabe = _string
End Function



mfG
BoGe-Ro

funkheld
21.10.2010, 12:00
Nimm AVR-Studio als Simulator.

Vergess das Ding von Bascom.

gruss