C# Ganzzahl wandeln in Gleitpunktzahl IEEE 754

sparx

Level-1
Beiträge
8
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo

Ich suche eine Funktion mit der ich in C# eine Dezimalzahl in eine Gleitpunktzahl im STEP7 Format bekomme.

In Step7 kann man in Varibalen Beobachten Steuern einfach das Anzeige Format ändern, wo man dann auch die beiden Werte sehen kann.

Operand Anzeigeformat Statuswert
DB5.DBD 80 DEZ L#1056964608
DB5.DBD 80 GLEITPUNKT 0.5

Ein einfachse Konvertieren zu double oder float in C# funktioniert nicht.

In S7 gibt es den Befehl DTR der das macht.
Dieser Befehl hält sich an die Norm IEEE 754.

Ich konnte aber leider keine fertige Funktion finden die eine Saubere Umwandlung hinbekommt.

Habe selbst versucht das nachzuprogrammieren. Meine Funktion zeigt vor dem Komma richtige aber nach dem Komma falsche Werte an.
Außerdem stürzt das Programm bei bestimmten Werten ab...:sm7:


Kennt da jemand eine Lösung?
Würde mich über Antwort freuen.

Gruß
Sparx
 
Keine Ahnung wie man das in C# macht, aber in C würde ich das so machen:
Code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
    int test = 1056964608;
    float *test2 = &test;
    float test3 = *test2;
    printf("%f", test3);
    return 0;
}
 
Zuviel Werbung?
-> Hier kostenlos registrieren
aus der S7net:

Code:
*
        #region ToByteArray
        public static byte[] ToByteArray(double value)
        {
            double wert = (double)value;
            string binString = "";
            byte[] bytes = new byte[4];
            if (wert != 0f)
            {
                if (wert < 0)
                {
                    wert *= -1;
                    binString = "1";
                }
                else
                {
                    binString = "0";
                }
                int exponent = (int)Math.Floor((double)Math.Log(wert) / Math.Log(2.0));
                wert = wert / (Math.Pow(2, exponent)) - 1;

                binString += ValToBinString((byte)(exponent + 127));
                for (int cnt = 1; cnt <= 23; cnt++)
                {
                    if (!(wert - System.Math.Pow(2, -cnt) < 0))
                    {
                        wert = wert - System.Math.Pow(2, -cnt);
                        binString += "1";
                    }
                    else
                        binString += "0";
                }
                bytes[0] = (byte)BinStringToByte(binString.Substring(0, 8));
                bytes[1] = (byte)BinStringToByte(binString.Substring(8, 8));
                bytes[2] = (byte)BinStringToByte(binString.Substring(16, 8));
                bytes[3] = (byte)BinStringToByte(binString.Substring(24, 8));

            }
            else
            {
                bytes[0] = 0;
                bytes[1] = 0;
                bytes[2] = 0;
                bytes[3] = 0;
            }
            return bytes;
        }
 
Aus libnodave.net

Aus libnodave.net.cs:

Code:
public static void putFloatat(byte[] b, int pos, Single value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            if (BitConverter.IsLittleEndian)
            {
                b[pos + 3] = bytes[0];
                b[pos + 2] = bytes[1];
                b[pos + 1] = bytes[2];
                b[pos] = bytes[3];
            }
            else
                Array.Copy(bytes, 0, b, pos, 4);
        }
 
Danke für die Antworten.

Meine kommt hier etwas sehr spät da ich zwischenzeitlich keine Zeit zum testen hatte.
Mir gefiel funkey´s Lösung am besten weils einfach die Simpelste ist.
Ich habe da etwas rum Probiert und mit folgenden änderungen läufts.

So funktioniert es:

Code:
static void Main(string[] args)
        {
            unsafe
            {
                int test = 1056964608;
                float* test2 = (float*)(int*)&test;
                float test3 = *test2;
                Console.WriteLine(test3.ToString());
            }
        }
 
Zurück
Oben