Konwersja "float to binary"

0

Na wstępie chciałem wszystkich miło powitać, dzień dobry ;)

Przywiódł mnie na forum pewien problem, którego jak na razie nie mogę rozwiązać.
Otóż mam za zadanie napisać program w C, który zamieni liczbę zmiennoprzecinkową (float) na binarną oraz podać znak, mantysę i cechę.

Nie mam problemu przy zamianie np. int, fragment mojego kodu:

void konwersja(int liczba, int podstawa)
{
    if (liczba==0) return;
    int wynik = liczba%podstawa;
    liczba /= podstawa;
    konwersja(liczba, podstawa); 
    if (wynik < 10) 
        printf("%i ",wynik);   
    else 
    {
        char litera = wynik + 55;
        printf("%c",litera);
    }

}

Lecz problem pojawia się, gdy w grę zaczynają wchodzić liczby float.
Prosiłbym o jakąś wskazówkę jak się za to zabrać ;)

Pozdrawiam
f.

1

http://pl.wikipedia.org/wiki/IEEE_754
Najprościej - przepisz do unsigned za pomocą memcpy() lub użyj union.

0

Dziekuje za odpowiedz. Czytalem o tej reprezentacji, tak samo jak interesujace bylo np. to : http://kipirvine.com/asm/workbook/floating_tut.htm

Szczerze mowiac nie chcialbym tego robic w najprostszy sposob, ale bardziej matematycznie.
Czy duzym bledem byloby gdybym zrobil rzutowanie float na int aby obcielo czes dziesietna i zamienic to na binarne? Po kropce binarnej znalazla by sie czesc ulamkowa po konwersji wg. schematu:

Algorytm przedstawiania ułamka u w binarnym systemie pozycyjnym.
Założenie: 0< u <1.
Napisz 0.. Kolejne cyfry rozwinięcia binarnego będziemy generować w następujący sposób:
Dopóki otrzymujesz nienapotkane wcześniej wartości u wykonuj
1. Pomnóż u przez 2
2. Jeżeli otrzymana wartość jest mniejsza od 1, to dopisz cyfrę 0
3. Jeżeli otrzymana wartość jest równa co najmniej 1, dopisz cyfrę  1 i odejmij od 
   wyniku 1. Z chwilą, gdy powtórzy się wartość u, zakończ procedurę; wypisany ciąg 
   jest okresowy, a jego okresem jest ciąg bitów między powtórzeniami.   

Oczywiscie sama czesc ulamkowo zdobylbym poprzez odejmowanie pierwszego float po rzutowaniu od float wejsciowego.

Nie wiem tylko jak potem zabrac sie za mantyse, ceche bo znak jest oczywisty.
Czy to rozumowanie jest poprawne?

1

float x=3E30; - do żadnego int'a się nie zmieści.

float x=3E30;
unsigned X;
memcpy(&X,&x,sizeof(x));
unsigned mantysa=X&((1<<23)-1);
unsigned wykładnik=(X>>23)&((1<<8)-1);
unsigned sign=X>>31;
0
_13th_Dragon napisał(a):

float x=3E30; - do żadnego int'a się nie zmieści.

float x=3E30;
unsigned X;
memcpy(&X,&x,sizeof(x));
unsigned mantysa=X&((1<<23)-1);
unsigned wykładnik=(X>>23)&((1<<8)-1);
unsigned sign=X>>31;

Tak rozumiem, sugerujesz, że nie ma co tracić pamięci i czasu jeżeli istnieje lepszy sposób? :)
Ok mam rozumieć, że dla double będzie to standard "IEE-754 double" czyli dla tego kodu zamiana 8 -> 11; 23->52; 31->63 ?

Moglbym prosic o podrzucenie jakiegos ciekawego artykulu jesli chodzi o przechowywanie pamieci, przesuniecia bitowe i operacje logiczne w c?

1
formalny napisał(a):

Moglbym prosic o podrzucenie jakiegos ciekawego artykulu jesli chodzi o przechowywanie pamieci, przesuniecia bitowe i operacje logiczne w c?

& - oraz tak jak w normalnej logice lecz dla każdego bitu osobno
| - lub tak jak w normalnej logice lecz dla każdego bitu osobno
^ - "czy rózne" dla każdego bitu osobno
przesunięcie << dopisanie odpowiedniej liczby zer z prawej strony w kodzie bitowym
przesunięcie >> usunięcie odpowiedniej liczby cyfr z prawej strony w kodzie bitowym

ot cała filozofia.

0

Ok dziekuje bardzo za pomoc.

Jeszcze glupie pytanie: Czy unsigned to skrot do unsigned int? Jak wyswietlic/wydrukowac poprawnie zawartosc z pamieci patrzac na powyzszy kod?
Oczywiscie wiem, ze memcpy potrzebuje biblioteki string.h

0

Ad.1. tak.
Ad.2. printf("%f",x);

0

Tak myślałem i tak zrobiłem. Ale przy próbie np. wydrukowania mantysy są same 0.

0

Przeczytaj ten artykuł i dowiedz się jak ta mantysa jest kodowana

0

Wiem, że znak jest zapisywany za pomocą 1 bitu, cecha 8 bitów, a mantysa 23 bitów z pominięciem wiodącego niezerowego.
Wszystkie bity mogą być zerami, ale np. w kodzie z nadmiarem albo jak wyjdziemy poza zakres.

Dla przykładu chcę wziąć prostą liczbę np. 1+1/2 czyli 1.5 w systemie dziesiętnym.
Powinno wyjść tak:

postać binarna: 00000000 00000000 11000000 00111111
mantysa: 10000000000000000000000
cecha: 01111111
znak: 0

a output dostaje:
4194304.000000
4194304.000000
4194304.000000

Podejrzewam, że rozwiązanie jest banalne, ale zawsze wszystko robiłem na intach i pierwszy raz szczerze mówiąc mam doczynienia z memcpy.

0
formalny napisał(a):

Powinno wyjść tak:

postać binarna: 00000000 00000000 11000000 00111111
mantysa: 10000000000000000000000
cecha: 01111111
znak: 0

I tak jest:

#include <stdio.h>
#include <string.h>
 
int main()
  {
   float x=1.5;
   unsigned X;
   memcpy(&X,&x,sizeof(x));
   unsigned mantysa=(X&((1<<23)-1))|(1<<23);
   unsigned wykladnik=(X>>23)&((1<<8)-1);
   unsigned sign=X>>31;
   printf("mantysa=%08o; wykładnik=%03o; sign=%o\n",mantysa,wykladnik,sign);
   return 0;
  }

http://ideone.com/36P0FH
ale wygląda na to że nie jesteś w stanie tego poprawnie wydrukować.

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