Forum: PC-Programmierung VB2008 Zahl von Kleinsteuerung konvertieren 65534 = -0.2?


von Katastrophe (Gast)


Lesenswert?

Hallo Leute,

Logge bei einer Kleinsteuerung auf eine MicroSD Karte.
Leider ist bei dieser Chinesensteuerung kein vernünftiger Support 
gegeben.

Darum muss ich mir selbst ein Programm zum einlesen und konvertiren in 
CSV schreiben. Wie kann ich aber folgende Wertetabelle vernünftig 
konvertiren ???

6  = 0.6
5  = 0.5
4       = 0.4
3  = 0.3
2  = 0.2
1  = 0.1
0  = 0.0
65535   =-0.1
65534   =-0.2
65533   =-0.3
65532   =-0.4
65531   =-0.5

Habe es wie folgt probiert, aber leider rundet mir VB was weg.

    Function CorrectNumber(ByRef Analogflag As String) As String
        Dim Zahl As Double

        Zahl = Val(Analogflag)
        If Zahl >= 32767 Then
            CorrectNumber = ((65535 - Zahl) * -1) / 10
        Else
            CorrectNumber = Analogflag / 10
        End If
    End Function

Weis jemand Rat?

von Peter II (Gast)


Lesenswert?

ist doch ein ganz normales Zweierkomplement

http://de.wikipedia.org/wiki/Zweierkomplement

warum willst du es überhaupt als Double verwenden? Lass doch das /10 weg 
und rechne mit int. Dann gibt es auch kein Roundungsproblem. Für die 
Anzeige rechtest du dann durch 10 und rundest auf 1 stelle nach dem 
Komma.

von Roland P. (pram)


Lesenswert?

Schaut so aus als ob das ein 16 bit Integer mit Fixed-Point ist.
1
Dim Zahl As Integer
2
Zahl = Val(Analogflag)
3
If Zahl >= 32767 Then Zahl = Zahl - 65536
4
5
CorrectNumber = CStr(Zahl / 10)
6
' oder
7
CorrectNumber = CStr(Zahl div 10) + "." + CStr(abs(Zahl mod 10))

(Ob das korrektes VB ist, weiß ich nicht)

Gruß
Roland

von Michael A. (micha54)


Lesenswert?

Hallo,

also im vorgenannten Text muß Zahl natürlich als Long definiert werden, 
sonst läuft der Wert bereits bei der VAL-Funktion über.

Integer ist niemals größer als 32767 !

Übrigens ist die Darstellung des Dezimalkommans als "." oder "," hier 
abhängig von den Einstellungen der Locales des Users, sollte man so 
nicht formulieren.

Gruß,
Michael

von Katastrophe (Gast)


Lesenswert?

Bin ein bischen schlauer geworden:

5  = 0.5 = 0000000000000101
4       = 0.4 = 0000000000000100
3  = 0.3 = 0000000000000011
2  = 0.2 = 0000000000000010
1  = 0.1 = 0000000000000001
0  = 0.0 = 0000000000000000
65535   =-0.0 = 1111111111111111
65534   =-0.1 = 1111111111111110
65533   =-0.2 = 1111111111111101
65532   =-0.3 = 1111111111111100
65531   =-0.4 = 1111111111111011

Aber wie in VB ordentlich lösen?

Zahl -> Binär -> Alle 0 und 1 invertieren -> wieder nach Zahl -> Zahl / 
10

von Peter II (Gast)


Lesenswert?

Katastrophe schrieb:
> Aber wie in VB ordentlich lösen?
>
> Zahl -> Binär -> Alle 0 und 1 invertieren -> wieder nach Zahl -> Zahl /
> 10


wozu binär, du hast doch schon den int wert?

Was kommt bei mir genau rein? eien CSV mit Text oder binary daten?

von Katastrophe (Gast)


Lesenswert?

Von der SD Karte lese ich Integer Werte in einer TXT Datei.
Wie kann ich einen kompletten Integerwert invertieren?

von Katastrophe (Gast)


Lesenswert?

Habe gerade folgende probiert:

Zahl -> Binär -> Alle 0 und 1 invertieren -> wieder nach Zahl ->
Zahl = Zahl * -1 -> Zahl / 10

Das funktioniert.

Müsste doch irgendwie ohne Umweg zu binär gehen, oder?

von Karl H. (kbuchegg)


Lesenswert?

Katastrophe schrieb:
> Von der SD Karte lese ich Integer Werte in einer TXT Datei.

wie genau liest du ein.

Wenn du in eine 16 Bit vorzeichenbehaftete Integer Variable (wie auch 
immer dieser Datentyp im VB heißt) die beiden Bytes direkt einliest, 
brauchst du normalerweise überhaupt nichts tun.

Denn die Bytes (jetzt mal abgesehen von der Bytereihenfolge) sind schon 
im 2-er Komplement, welches auch dein 16-Bit Integer mit Vorzeichen 
benutzt.

Du machst dir da zu viel Arbeit und verkomplizierst die Dinge unnötig.

von Katastrophe (Gast)


Lesenswert?

Lese mit System.IO.File.ReadAllLines ein.
Diese werden in eine Listbox kopiert, weil die einzelnen Zeilen noch "0" 
und "1" für Relais und andere Zustände der Kleinsteuerung enthalten.
Darum kann ich es nicht besser einlesen.

von Peter II (Gast)


Lesenswert?

Katastrophe schrieb:
> Diese werden in eine Listbox kopiert, weil die einzelnen Zeilen noch "0"
> und "1" für Relais und andere Zustände der Kleinsteuerung enthalten.
> Darum kann ich es nicht besser einlesen.

was soll denn das für ein Grund sein. eine Listbox ist ein GUI element 
das nimmt man nicht für eine Datenverarbeitung. Was ist wenn dein 
Programm kein Gui hat?

Kannst du mal so eine Textdatei hochladen?

von Karl H. (kbuchegg)


Lesenswert?

Moment.
Ist das eine Textdatei?

> Kannst du mal so eine Textdatei hochladen?

Hätte ich auch gesagt. Jetzt wirds Zeit dafür.

von Katastrophe (Gast)


Angehängte Dateien:

Lesenswert?

Habe mal die Dateien angehangen.
Din Binflags hat binäre Zustände der Steuerung.
Die Dezflags hat die analogen Zustände der Steuerung.
Beide müssen kombiniert werden, und über einen Filter ausgewertet 
werden.

von Peter II (Gast)


Lesenswert?

> Habe mal die Dateien angehangen.
> Din Binflags hat binäre Zustände der Steuerung.
> Die Dezflags hat die analogen Zustände der Steuerung.

kannst du noch dazu sagen um welchs Feld es geht?

von axelr (Gast)


Lesenswert?

18.3MB -> und ich - in der S-Bahn - drück da auch noch drauf ;(

von axelr (Gast)


Lesenswert?

65534 -> StrToInt -> / 10

sollte doch gehen, oder?

von Karl H. (kbuchegg)


Lesenswert?

Katastrophe schrieb:
> Habe mal die Dateien angehangen.

Noch größere hast du nicht gefunden?

Mann, mann, mann.
Bissi mitdenken! Keiner hier wusste, dass deine Dateien so groß sind. In 
diesem Fall hätte es ein Auszug aus dem Dateianfang auch getan. Wir 
wollen doch nur sehen, wie die prinzpiell aussehn, mehr nicht.
Und dafür lad ich mir sicher nicht 25MB runter.

Ganz davon abgesehen, dass eine 'kleine Version' der Daten auch während 
der Programmentwicklung nützlich ist. Oder willst du während der 
Entwicklung laufend riesige Files wieder und immer wieder einlesen?

von Katastrophe (Gast)


Lesenswert?

axelr schrieb:
> 65534 -> StrToInt -> / 10

Würde dann aber 6553.4 ergeben :-(

Sorry wegen der Grösse.
Habe ich bei VDSL übersehen ;-)

Die Felder mit den >65000 sind gefragt. Codierung wie schon oben 
beschrieben:
Zahl -> Binär -> Alle 0 und 1 invertieren -> wieder nach Zahl ->
Zahl = Zahl * -1 -> Zahl / 10

von Malte S. (maltest)


Lesenswert?

Kriegst Du die Textdatei in genau der Form oder hast Du die schon 
bearbeitet?
Denn da steht ja gar nicht 65535 drin, sondern schon 6553.5. Ist das 
Komma original?
Das dämlichste, was den Daten auf dem Weg in diese Darstellung passiert 
ist, ist ja, dass ein 16 signed int (der * .1 skaliert zu interpretieren 
ist) als 16-bit unsigned int (und dann evtl. schon * .1 skaliert ist) 
ausgegeben wird.
So oder so:

1. Komma entfernen, falls es nicht erst durch Dich da rein gekommen ist
2. Textdarstellung in 16-bit unsigned int umwandeln
3. Ergebnis von #2 brutal nach 16-bit signed int casten
4. Ergebnis von #3 unter Umwandlung in Fest- oder Fließkomma durch 10 
teilen

Schritte #2-#4 in C:

(int16_t)strtoul(string_value_without_decimal_point, NULL, 10) / 10.0

Schritt #3 ist der alles entscheidende. Ob VB zu dieser Verrenkung in 
der Lage ist, ohne eben über die Binärdarstellung zu gehen, weiß ich 
nicht. Aber vielleicht findest Du ja dazu was. Uminterpretation unsigned 
=> signed.

von Rudi (Gast)


Lesenswert?

Hey Leute.

Scheinbar nehme ich die gleiche Steuerung her :-D

Selbes Problem, selbe Sprache (VB2010).

Habe es wie folgt gelöst:
1
    Public Function CorrectNumber(ByVal StringNumber As String) As Double 'Richtigen Wert ermitteln
2
        Dim helpstring As String
3
        helpstring = StringNumber.Replace(".", "")      'String übergeben und Punkte entfernen
4
        If Int(StringNumber < 32767) Then
5
            CorrectNumber = Int(StringNumber) / 10
6
        Else
7
            helpstring = Decimal2Binary(Int(StringNumber))  'In Binär wandeln
8
            helpstring = helpstring.Replace("0", "T") 'Bin Wert invertieren
9
            helpstring = helpstring.Replace("1", "0") 'Bin Wert invertieren
10
            helpstring = helpstring.Replace("T", "1") 'Bin Wert invertieren
11
            CorrectNumber = Binary2Decimal(helpstring) / -10 'In Integer wandeln und minusvorzeichen setzen
12
        End If
13
    End Function
14
15
16
    ' Dezimal nach Binärzahl umwandeln
17
    Public Function Decimal2Binary(ByVal Dec As Integer) As String
18
        Return Convert.ToString(Dec, 2)
19
    End Function
20
21
    ' Binärzahl nach Dezimal umwandeln
22
    Public Function Binary2Decimal(ByVal Bin As String) As Integer
23
        Dim l As Integer
24
25
        For i As Integer = 0 To Bin.Length - 1
26
            l = (l << 1) + Integer.Parse(Bin.Substring(i, 1))
27
        Next
28
        Return l
29
    End Function

Würde trotzdem einen kürzeren Code als angenehm entfinden :-D

von Arc N. (arc)


Lesenswert?

Rudi schrieb:
> Würde trotzdem einen kürzeren Code als angenehm entfinden :-D

Zwar C#
double d = Convert.ToInt16("1111111111111110", 2) / 10.0;
bzw.
double d = (Int16)Convert.ToUInt16(65535) / 10.0;

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Ich kann mir nicht vorstellen, dass das hier
1
        If Int(StringNumber < 32767) Then
korrekt ist.

Warum ihr da unbedingt über binär gehen müsst erschliesst sich mir 
überhaupt nicht.
Selbst wenn ein int in VB mitlerweile 32 Bit groß ist, wo genau liegt 
jetzt das Problem in
1
   Zahl = int( string )
2
3
   if( Zahl > 32767 )
4
     Zahl = Zahl - 65536
5
6
   Ergebnis = Zahl / 10

Das die Gleitkommadarstellung der Zehntel nicht immer 100% exakt ist, 
liegt an der Gleitkommadarstellung an sich und muss in den weiteren 
Berechnungen berücksichtigt werden.

: Bearbeitet durch User
von Kurt (Gast)


Lesenswert?

Arc Net schrieb:
> Zwar C#
> double d = Convert.ToInt16("1111111111111110", 2) / 10.0;
> bzw.
> double d = (Int16)Convert.ToUInt16(65535) / 10.0;

Das geht unter VB schief !!!

von Arc N. (arc)


Lesenswert?

Kurt schrieb:
> Arc Net schrieb:
>> Zwar C#
>> double d = Convert.ToInt16("1111111111111110", 2) / 10.0;
>> bzw.
>> double d = (Int16)Convert.ToUInt16(65535) / 10.0;
>
> Das geht unter VB schief !!!

Ja, hatte tatsächlich vergessen, dass so was in VB einen Overflow 
ergibt...
Dann die Holzhammermethode...
1
BitConverter.ToInt16(BitConverter.GetBytes(Convert.ToUInt16(65535)), 0) / 10.0

von Rudi (Gast)


Lesenswert?

Arc Net schrieb:
> Dann die
> Holzhammermethode...BitConverter.ToInt16(BitConverter.GetBytes(Convert.T 
oUInt16(65535)),
> 0) / 10.0

Wahnsinn. Das funktioniert wirklich super !!!!

Dankeschön!!!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.