Reprezentacja liczb typu float

Odpowiedz Nowy wątek
2015-09-12 23:11
0

Witam, to już chyba codzienność tego forum, że piszę z jakimś problemem. Robię zadanie: http://pl.spoj.com/problems/PP0504D/

Nabazgrałem coś takiego i doszedłem do wniosku, że to wszystko źle, bo to tylko jedna by starczyła jakby ją zapętlić. Jakaś podpowiedź jak to zrobić?

Myślicie, że jak mam problemy z takimi zadaniami to robić kolejny kurs czy mogę męczyć się z tymi zadaniami, bo te łatwiejsze z łątwych to bez problemu ogarniam praktycznie :P

#include <iostream>
#include <conio.h>
#include <math.h>
using namespace std;
int a;
int b=0;
int f=0;
int x=0;
int main()
{
    cin >>a;
    do
    {
        b++;
    }
    while (a>pow( 16, b ));
    int c = a/pow(16, b-1);
//pierwsza cyfa
    if (c<10)
        cout <<c;
    else if (c==10)
        cout<<"A";
    else if(c==11)
        cout <<"B";
    else if(c==12)
        cout <<"C";
    else if(c==13)
        cout<<"D";
    else if(c==14)
        cout <<"E";
    else if(c==15)
        cout <<"F";
    int e=pow(16, b-1);
    int d=a%e;
    do
    {
        f++;
    }
    while (d>pow( 16, f ));
    int z = d/pow(16, f-1);

//druga cyfra
    if (z<10)
        cout <<z;
    else if (z==10)
        cout<<"A";
    else if(z==11)
        cout <<"B";
    else if(z==12)
        cout <<"C";
    else if(z==13)
        cout<<"D";
    else if(z==14)
        cout <<"E";
    else if(z==15)
        cout <<"F";
    int h=pow(16, f-1);
    int g=d%h;
    {
        x++;
    }
    while (g>pow( 16, x ));
    int y = g/pow(16, x-1);
    cout <<y;
    return 0;
}

Pozostało 580 znaków

2015-09-13 00:31
3

Może na razie przedstawię jak to zrobić na przykładzie jednej liczby zmiennoprzecinkowej:

Fakty podstawowe:

  • sizeof w C podaje rozmiar typu w postaci wielokrotności rozmiaru char
  • na procesorach w architekturze x86 char odpowiada 1 oktetowi bitów (zwanemu też bajtem)

Tak więc float zajmuje dokładnie tyle samo miejsca w pamięci co char[sizeof(float)]. Zapiszmy to w postaci unii:

union Repr {
  float f;
  char b[sizeof(float)];
}

Dzięki przeczytaniu dokumentacji funkcji printf wiemy, że istnieją flagi x oraz X, które wyświetlają liczby w zapisie szesnastkowym (odpowiednio małymi i wielkimi literami).

Tak więc wyświetlenie reprezentacji bitowej jednego floata w postaci szesnastkowej to:

Repr rep;
rep.f = 0.12345f;
printf("%x %x %x %x", rep.b[3] & 0xff, rep.b[2] & 0xff, rep.b[1] & 0xff, rep.b[0] & 0xff);

Kolejność wyświetlania od najstarszego bajtu zgodnie z treścią zadania. Mapowanie jest potrzebne ze względu na rzutowanie wartości na int przed wyświetleniem, a wtedy pojawiają się zbędne ustawione bity.

Nie ma szans, by rep.b[3] &amp; 0xff nie było równe rep.b[3], jeśli rep.b jest tablicą char. nie mogą się żadne ustawione bity pojawić, bo ich na tym etapie nie ma. możesz natomiast dodać rzutowanie na unsigned int, to ma większy sens: (unsigned)rep.b[3] - Azarien 2015-09-13 01:42
może użyć zamiast char uint8_t - kaczus 2015-09-13 08:25
unsigned char b[sizeof(float)]; i &amp; 0xff staje się zbędne. - MarekR22 2015-09-13 11:07
Btw. To jest ok tylko w C. W C++ używanie unii w ten sposób to UB. - Endrju 2015-09-13 21:37
GCC konkretnie pozwala na aliasing w uniach i nie jest to UB. Visual C++ chyba też. - Azarien 2015-09-13 23:51

Pozostało 580 znaków

2015-09-13 11:26
2

jak już używasz STL-a to skorzystaj z manipulatorów: cout << hex << x;.

void printfloat(float x) {
    unsigned char * const bytes = (unsigned char *)&x;
    cout << hex << (int)bytes[3] << " "
        << hex << (int)bytes[2] << " "
        << hex << (int)bytes[1] << " "
        << hex << (int)bytes[0] << endl;
}

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.

Pozostało 580 znaków

2015-09-13 16:53
0

Uzyskałem taki kod, program poprawnie konwertuje (tak myślę!) liczbę dziesiętną na liczbę szesnastkową, ale nie do końca rozumiem autora zadania co do wyjścia: "bajty reprezenacji kolejnych liczb".
Pomocy!

#include <iostream>
#include <conio.h>
#include <math.h>
using namespace std;
float a;
int b;
int c;
int d;
float e;
int main()
{
  cin >>a;
       do
    {
        b++;
    }
    while (a>pow( 16, b ));

do{
        c=a/pow( 16, b-1 );

        d=pow(16, b-1);
        e = a-c*pow( 16, b-1 );

a=e;
        b--;
 if (c<10)
        cout <<c;
    else if (c==10)
        cout<<"A";
    else if(c==11)
        cout <<"B";
    else if(c==12)
        cout <<"C";
    else if(c==13)
        cout<<"D";
    else if(c==14)
        cout <<"E";
    else if(c==15)
        cout <<"F";
}while(b!=0);
    return 0;
}

Pozostało 580 znaków

2015-09-13 19:15
1

Niepotrzebnie kombinujesz. bajty reprezenacji kolejnych liczb znaczą tyle co po prostu bajty w hexie danej zmiennej. Koledzy up ci pokazali jak możesz to zrobić, pisanie funkcji konwertującej jest tu całkowicie zbędne.
Jak coś, zostawie ci kod z mojego spoja, syfiasty strasznie, bo daawno już to robiłem ;p

#include <stdio.h>
int main(void)
{
    char t;
    float s;
    size_t i;
    scanf("%i", &t);
    unsigned char *d;
    while(t--)
    {
        scanf("%f", &s);
        for(i = sizeof(s);i>0; --i)
        {
            if(((i/2!=0) && (i!=sizeof(s))) || (i==1))printf("  ");
            printf("%x", ((unsigned char *)&s)[i-1]);
        }
        printf("\n");
    }
}

Pozostało 580 znaków

2015-09-13 22:30
0

Dzięki wielkie wszystkim za pomoc i wytłumaczenie :)
Program do konwersji może się kiedyś przyda tymczasem biorę pod warsztat od nowa to zadanie :P

Pozostało 580 znaków

2015-11-22 20:58
Anim
0

hej :) napotkałem na taki sam problem jak opisywany powyżej. i czy ktoś mógłby mi podesłać link, gdzie jest opisana to , co sdzieje sięw kodach u góry? Dla mnie w kodzie 16-owym powiedzmy 1 to 1..natomiast w odpowiedzi do zadanego zagadnienia to 3f 80 0 0...o co w tym chodzi ? proszę o pomoc, ewentualne o wytłumaczenie :) Dziękuję

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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