Liczby zmiennoprzecinkowe a zamiana na system binarny

0

Cześć wszystkim,

Jeśli chodzi o typ całkowitoliczbowy (np. int) to można przypisać mu wartość również przez int a = 0b1000011000.
Aby podglądnąć reprezentację binarną wystarczy string binary = Convert.ToString(number, 2) (dlaczego nie działa to dla liczb ujemnych, to znaczy działa poprawnie z tym, że najbardziej znaczące bity mają wartość 1).

A teraz chciałbym zrobić to samo tylko dla typu double, ale z tą różnicą, że wykorzystam do tego notację naukową (tak jak to domyślnie komputer robi).
Tutaj link do artykułu, z którego korzystałem: https://www.samouczekprogramisty.pl/liczby-zmiennoprzecinkowe/
Ale jest problem...
double a = 0b1000101010100101010100011000001 jest traktowane jako liczba całkowita, a nie notacja naukowa
string binary = Convert.ToString(number, 2), gdzie number to typ double nie działa

Takie 3 problemy napotkałem i nie mogę ich przeskoczyć.

wielkie dzięki za pomoc,
miłego dnia

2

dlaczego nie działa to dla liczb ujemnych, to znaczy działa poprawnie z tym, że najbardziej znaczące bity mają wartość 1

Strzelam, że chodzi ci o kod U2: https://pl.wikipedia.org/wiki/Kod_uzupe%C5%82nie%C5%84_do_dw%C3%B3ch

double a = 0b1000101010100101010100011000001 jest traktowane jako liczba całkowita, a nie notacja naukowa

Literały z b są traktowane zawsze jako liczby całkowite. Tak definiuje standard C#.

string binary = Convert.ToString(number, 2), gdzie number to typ double nie działa

Najlepiej ci będzie wykorzystać BitConverter:

double d = BitConverter.Int64BitsToDouble(Convert.ToInt64(binary, 2));
2

Co do ujemnych integerów binarnie, są one inaczej kodowane, bit z lewej to bit znaku, dlatego 32 - bitowa integer ma zakres od -2^31 do 2^31 - 1, gdyż jeden bit idzie na znak. Kodowane można przedstawić tak:
~|a| + 1;
czyli liczba ujemna to negacja bitowa wartości bezwzględnej z liczby plus jeden. Dla -2(dla uproszczenia 8-bitowo):
~|-2| + 1 =>
~00000010 + 1 =>
11111101 + 00000001 =
11111110.
Stąd jedynki na początku.

EDYCJA: Bity liczby double. Zgodnie ze specyfikacją double to zmienna 64-cztero bitowa, od bitu 63-ciego:
bit znaku;
11 bitów wykładnika;
53 bity mantysy, przy czym bit 53-trzeci jest równy jeden.
Czyli, wartość wynosi:
(-1)^bit znaku * (1, mantysa) * 2 ^(wykładnik - 1023).
Odejmowanie 1023 - takie kodowanie.
Przykład, weźmy hexagonalne: 3F F0 00 00 00 00 00 00 w Big Endian:
Bit znaku = 0, czyli (-1)^0 = 1 - liczba dodatnia;
Wykładnik: 3FF, czyli 011 1111 1111 = 1023(dec) (pierwszy bit poszedł na znak);
Mantysa: 1, 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 czyli 1.0 (decymalnie).
Finalnie: (-1) ^ 0 * (1, 0) * 2^(1023 - 1023) = 1 * (1,0) * 1 = 1.0.
Możesz spróbować napisać konwerter, generalnie:

  1. Zapisujesz bity liczby float do bajtów.
  2. Kastujesz to do uint_64.
  3. Teraz:
1
Barteker napisał(a):

double a = 0b1000101010100101010100011000001 jest traktowane jako liczba całkowita, a nie notacja naukowa

To to samo co double a = 1163045057, dlaczego miałoby być „notacją naukową”?

1

Nie notacja naukowa tylko IEEE 754 double-precision binary floating-point format: binary64

Chociaz powiedzmy ze jest to faktycznie odmiana notacji naukowej* ;)

0

Dziękuję za odpowiedzi, teraz mi się dużo rozjaśniło.

0

Dodajmy, nie wiem czy TY też tego oczekujesz, wielu oczekuje, żeby liczba pamiętała "jak została zainicjowana", sposobem binarnym, dziesiętnym, hexem itd...
Nie ma czegoś takiego, liczba to po prostu liczba.

0

Możesz użyć specjalnej klasy do konwertowania
Najpierw zamieniasz liczbę double na 8 bajtów a potem ewentualnie te bajty na bity . W drugą stronę tak samo
albo możesz zrobić sobie sam konwerter do każdego rodzaju typu np.

 using System;
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] bity = ZamienNaBity(-0b1111111111111111111111111111111);
            Console.WriteLine(-0b1111111111111111111111111111111);
            for (int i = 0; i < 32; i++)
            {
                Console.Write(bity[i]);
            }
            Console.WriteLine();
            bity = ZamienNaBity(-27.0F);
            for (int i = 0; i < 32; i++)
            {
                Console.Write(bity[i]);
            }
            Console.WriteLine();
        }

        static byte[] ZamienNaBity(int liczbaI)
        {
            byte[] bity = new byte[32];

            for (int i = 31; i >= 0; i--)
            {
                if ((liczbaI & 1) == 1) bity[i] = 1;
                else
                    bity[i] = 0;
                liczbaI = liczbaI >> 1;
            }
            return bity;
        }

        static byte[] ZamienNaBity(float liczbaF)
        {
            byte[] bity = new byte[32];
            unsafe
            {
                int* t1 = (int*)&liczbaF;

                int liczbaI = *t1;

                for (int i = 31; i >= 0; i--)
                {
                    if ((liczbaI & 1) == 1) bity[i] = 1;
                    else
                        bity[i] = 0;
                    liczbaI = liczbaI >> 1;
                }
                return bity;
            }
        }
    }
}
0
using System;
namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] bity;
            bity = ZamienNaBity(0.5);
            for (int i = 0; i < 64; i++)
            {
                Console.Write(bity[i]);
            }
            Console.WriteLine();
            

        }

       

        static byte[] ZamienNaBity(double liczbaD)
        {
            byte[] bity = new byte[64];
            unsafe
            {
                long* t1 = (long*)&liczbaD;

                long liczbaL = *t1;

                for (int i = 63; i >= 0; i--)
                {
                    if ((liczbaL & 1) == 1) bity[i] = 1;
                    else
                        bity[i] = 0;
                    liczbaL = liczbaL >> 1;
                }
                return bity;
            }
        }
    }
}

0.5 = 0011111111100000000000000000000000000000000000000000000000000000
0.5F = 00111111000000000000000000000000
Zgadza się ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1