wartości binarne z floata do integera

wartości binarne z floata do integera
OL
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:27
0

Witam, mam za zadanie zamienić dane binarne reprezentujacę liczbę float na typ całkowito-liczbowy i za bardzo nie wiem jak się za to zabrać. Pamiętam, że prowadzący wspominał coś o wskaźnikach i adresach. Z góry dziękuję za pomoc. Program piszę w języku C.

stryku
  • Rejestracja:ponad 11 lat
  • Ostatnio:prawie 2 lata
  • Postów:607
0

Na moje to będzie

Kopiuj
float f = 2.0;
int a;
a = f; 

Ale to chyba nie o to chodzi. Sprecyzuj, podaj jakiś przykład bo nie wiem jak inni, ale ja chyba nie rozumiem

edytowany 1x, ostatnio: stryku
OL
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:27
0

chodzi o wartości binarne, czyli float 2.0 nie bedzie reprezentowany tak samo jak int bo bedzie mial inne pola chociażby mantysy

OL
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:27
0

CHodzi o to że powiedzmy kod 10101010101010101010101010101010 jest inna liczbą którą reprezentuje float i inną ktora reprezentuje int. Chodzi o to zeby pokazać właśnie te dwie rozne wartosci na wskaznikach

stryku
  • Rejestracja:ponad 11 lat
  • Ostatnio:prawie 2 lata
  • Postów:607
0

No tak. To chodzi Ci, że dostaniesz mantyse i ceche i zmieniasz to na liczbę?
Czy masz wskaźnik do float i z niego wyłuskujesz mantysę i cechę i wtedy zamieniasz to na liczbę?

Chodzi o to zeby pokazać właśnie te dwie rozne wartosci na wskaznikach tego nie rozumiem

Chodzi o coś takiego?

Kopiuj
void *ptr = coś;
printf( "float: %f\nint: %d", *ptr, *ptr );
 
edytowany 3x, ostatnio: stryku
merlinnot
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 lat
  • Lokalizacja:Wrocław
  • Postów:292
1
OL
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:27
0

to jest druga część tego zadania 1) przy pomocy wskaźników, 2) przy pomocy uni :D

Sopelek
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 8 lat
  • Lokalizacja:Kraków
  • Postów:467
0

W obu przypadkach to jest UB i nie powinno się tak robić.
Jedyne co możesz bezpiecznie zrobić to rzutować wskaźnik do char*.

Endrju
  • Rejestracja:około 22 lata
  • Ostatnio:ponad rok
1

Przy pomocy wskaźników - undefined behavior w C i C++. Można to "obejść" wyłączając strict aliasing w kompilatorze ale to nie jest dobre rozwiązanie. (W GCC -fno-strict-aliasing)
Przy pomocy unii - undefined behavior w C++, z pewnością well defined w >=C99 jeżeli typy mają takie same rozmiary. Ponadto np. GCC gwarantuje, że w C++ to też będzie działać.

Bezproblemową metodą działająca zawsze i wszędzie powinno być memcpy.


"(...) otherwise, the behavior is undefined".
edytowany 1x, ostatnio: Endrju
merlinnot
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 lat
  • Lokalizacja:Wrocław
  • Postów:292
0

Rozpisując się:

O typie float nie można nawet powiedzieć, że jest zmiennoprzecinkowy. Nie ma takiej gwarancji. Niektóre kompilatory gwarantują, że jest to 32-bitowa liczba zmiennoprzecinkowa (IEEE-754). Przy pomocy unii można zrobić to w ten sposób:

Kopiuj
#include <cinttypes>
#include <iostream>

union intFloat {
    uint32_t Int;
    float Float;
    intFloat (uint32_t i) : Int(i) { }
    intFloat (float f) : Float(f) { }
};

int main () {
    
    uint32_t intV = 1;
    intFloat iVU = intFloat(intV);

    float floatV = 1.0;
    intFloat fVU = intFloat(floatV);

    std::cout << iVU.Int
              << '\n'
              << iVU.Float
              << '\n'
              << fVU.Int
              << '\n'
              << fVU.Float
              << std::endl;
}

Lub przez memcpy:

Kopiuj
#include <cinttypes>
#include <iostream>
#include <cstring>

#ifndef __STDC_IEC_559__
#error "Size of float might not equal 32bit"
#endif

int main () {

    uint32_t intV = 1;
    float floatV;

    memcpy (&floatV, &intV, sizeof(int));

    std::cout << intV
              << '\n'
              << floatV
              << std::endl;
}
edytowany 1x, ostatnio: merlinnot
Endrju
Pierwszy kod - C++ - UB. Wątek ma w tagach C. float i double to SĄ typy zmiennoprzecinkowe i to standard gwarantuje.
spartanPAGE
+ serio, magiczne liczby w memcpy? Sizeof...
merlinnot
Po to był wstęp. Z resztą samo zadanie jest trochę undefined :)
merlinnot
@spartanPAGE co za różnica w kodzie na pięć linijek... To i tak jest wszystko brudne ze względu na brak wiedzy na temat float.
spartanPAGE
Ja nie jestem wredny. Ale jeśli kod na 5 linijek jest niskiej jakości to ja nie chcę widzieć sytuacji, w której będzie ich już 500.
Pebal
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad rok
  • Postów:111
1
Kopiuj
float f = 2.0f;
int i = *(int*)&f;
Zobacz pozostałe 24 komentarze
Endrju
Standard jasno mówi, że ten kod to totalna bzdura. Internet pełen jest przykładów dlaczego to bzdura i do czego prowadzi łamanie strict aliasing rule. Zadaj sobie trud szukania - najwyższy czas doedukować się po tych 18 latach nieznajomości podstaw. Już nic więcej nie poradzę, powodzenia.
Pebal
@Mokrowski, Mało mnie interesuje czy ten kod działa na C64 tym bardziej, że na C64 programowałem w Assemblerze.
Pebal
@Endrju, Zamiast tyle pisać o teorii wykaż, że ten kod nie działa.
MO
@Pebal AVR, MSP430, 8051, PIC kod nie_działa. Platformy ARM, PowerPC, OpenSparc (nie przechodzi statycznego sprawdzania linkerem). Kompilatory IAR, IBM, Microchip, TI, gcc. Uhm.. wiem.. to nie komputery. Uhm.. wiem.. od 18 lat.. alergia na standardy i czytanie przed.. Uhm.. Powodzenia :-/
Pebal
@Mokrowski, Przecież pisałem, że zachowanie jest zdefiniowane na konkretnych platformach. Ja rozumiem, że Ty piszesz kod, który musi działać na wszystkich możliwych platformach, ale ja i 99% programistów, takiego kodu pisać nie musi. Pomijam już to, że taki "przenośny" kod i tak często ma masę ifdef'ów, dedykowanych dla konkretnych platform.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.