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?
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.
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
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
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
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 der SD Karte lese ich Integer Werte in einer TXT Datei. Wie kann ich einen kompletten Integerwert invertieren?
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?
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.
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.
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?
Moment.
Ist das eine Textdatei?
> Kannst du mal so eine Textdatei hochladen?
Hätte ich auch gesagt. Jetzt wirds Zeit dafür.
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.
> 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?
18.3MB -> und ich - in der S-Bahn - drück da auch noch drauf ;(
65534 -> StrToInt -> / 10 sollte doch gehen, oder?
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?
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
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.
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
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
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
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 !!!
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 |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.