From 620a3a42e9ef0a6a9fed3ec5efa98e92870f009c Mon Sep 17 00:00:00 2001 From: Gustavo Martin Morcuende Date: Sun, 29 May 2016 14:31:34 +0200 Subject: [PATCH] IEE754 --- IEE754/Makefile | 11 ++++ IEE754/doubleconverter.c | 117 +++++++++++++++++++++++++++++++++++++++ IEE754/floatconverter.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+) create mode 100644 IEE754/Makefile create mode 100644 IEE754/doubleconverter.c create mode 100644 IEE754/floatconverter.c diff --git a/IEE754/Makefile b/IEE754/Makefile new file mode 100644 index 0000000..09493a9 --- /dev/null +++ b/IEE754/Makefile @@ -0,0 +1,11 @@ +all: floatconverter doubleconverter + +floatconverter: floatconverter.c + g++ -Wall -g -o floatconverter floatconverter.c + +doubleconverter: doubleconverter.c + g++ -Wall -g -o doubleconverter doubleconverter.c + +clean: + rm -f floatconverter + rm -f doubleconverter diff --git a/IEE754/doubleconverter.c b/IEE754/doubleconverter.c new file mode 100644 index 0000000..a27e562 --- /dev/null +++ b/IEE754/doubleconverter.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include +#include + +//using namespace std; + +union Double_t +{ + Double_t(double num) : f(num) {} + // Portable extraction of components. + bool Negative() const { return (i >> 63) != 0; } + int64_t RawMantissa() const { return i & ((1LL << 52) - 1); } + int64_t RawExponent() const { return (i >> 52) & 0x7FF; } + + int64_t i; + double f; +#ifdef _DEBUG + struct + { + // Bitfields for exploration. Do not use in production code. + // least significant bit (LSB): 2^0 + uint64_t mantissa : 52; // mantissa also called significand + uint64_t exponent : 11; + uint64_t sign : 1; + // most significant bit (MSB): 2^64 + } parts; +#endif +}; + + +int main (int argc, char *argv[]) +{ + std::cout << "******************************************************************************" << std::endl; + std::cout << std::endl; + std::cout << "(SIGN) MANTISSA * 2^(EXPONENT-1023) (using base 10)" << std::endl; + std::cout << std::endl; + std::cout << "******************************************************************************" << std::endl; + std::cout << std::endl; + + double number = atof(argv[1]); + Double_t mydouble(number); + + std::cout << std::setprecision(64); + std::cout << std::fixed; + std::cout << "Number after atof conversion (libc): "; + std::cout << number << std::endl; + std::cout.unsetf(std::ios::fixed); + + std::cout << std::endl; + std::string signo = mydouble.Negative() ? "negative" : "positive"; + std::cout << "Sign: " + signo << std::endl; + std::cout << std::endl; + + int64_t exponent = mydouble.RawExponent(); + std::bitset<11> exponent_bits(exponent); + std::cout << "Exponent, binary value: " << exponent_bits << std::endl; + std::cout << "Exponent, decimal value: " << exponent << std::endl; + std::cout << "Exponent, real value: " << exponent << " - 1023 = " << (exponent - 1023) << std::endl; + std::cout << std::endl; + + int64_t mantissa = mydouble.RawMantissa(); + std::bitset<52> mantissa_bits(mantissa); + std::cout << "Mantissa, binary value: " << mantissa_bits << std::endl; + std::cout << "Mantissa, hexadecimal value: "; + std::cout << std::hex << std::uppercase << std::setw(13) << std::setfill('0') << mantissa << std::endl; + std::cout << "Mantissa, binary value (fraction in base 2): 1." << mantissa_bits << std::endl; + std::cout << "Mantissa, decimal value: TODO" << std::endl; + std::cout << std::endl; + + + std::cout << std::endl; + std::cout << "Hexadecimal value (integer representation): "; + std::cout << std::hex << std::setw(16) << std::setfill('0') << std::uppercase << mydouble.i << std::endl; + + + return 0; +} + + + + +/*************************************************************************************************** + + + + me@mycomputer:~$ ./floatconverter 0.01 + ****************************************************************************** + + (SIGN) MANTISSA * 2^(EXPONENT-127) (using base 10) + + ****************************************************************************** + + Sign: positive + + Exponent, binary value: 01111000 + Exponent, decimal value: 120 + Exponent, real value: 120 - 127 = -7 + + Mantissa, binary value: 01000111101011100001010 + Mantissa, binary value (fraction in base 2): 1.01000111101011100001010 + Mantissa, decimal value: TODO + + + Hexadecimal value: 3C23D7A + me@mycomputer:~$ echo "ibase=2; 1.01000111101011100001010" | bc + 1.27999997138977050781250 + me@mycomputer:~$ echo "obase=10; scale=10; 1.27999997138977050781250*(2^-7)" | bc + .00999999977648258209228 <------------ closest integer (never 0.01) + + + + +******************************************************************************************************/ diff --git a/IEE754/floatconverter.c b/IEE754/floatconverter.c new file mode 100644 index 0000000..f88dc34 --- /dev/null +++ b/IEE754/floatconverter.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include + +//using namespace std; + +union Float_t +{ + Float_t(float num = 0.0f) : f(num) {} + // Portable extraction of components. + bool Negative() const { return (i >> 31) != 0; } + int32_t RawMantissa() const { return i & ((1 << 23) - 1); } + int32_t RawExponent() const { return (i >> 23) & 0xFF; } + + int32_t i; + float f; +#ifdef _DEBUG + struct + { + // Bitfields for exploration. Do not use in production code. + // least significant bit (LSB): 2^0 + uint32_t mantissa : 23; // mantissa also called significand + uint32_t exponent : 8; + uint32_t sign : 1; + // most significant bit (MSB): 2^31 + } parts; +#endif +}; + + +int main (int argc, char *argv[]) +{ + std::cout << "******************************************************************************" << std::endl; + std::cout << std::endl; + std::cout << "(SIGN) MANTISSA * 2^(EXPONENT-127) (using base 10)" << std::endl; + std::cout << std::endl; + std::cout << "******************************************************************************" << std::endl; + std::cout << std::endl; + + float number = atof(argv[1]); + Float_t myfloat(number); + + std::cout << "Number after atof conversion (libc): "; + std::cout << std::setprecision(32) << std::fixed << number << std::endl; + //std::cout.unsetf(std::ios::fixed); + + std::cout << std::endl; + std::string signo = myfloat.Negative() ? "negative" : "positive"; + std::cout << "Sign: " + signo << std::endl; + std::cout << std::endl; + + int32_t exponent = myfloat.RawExponent(); + int32_t mantissa = myfloat.RawMantissa(); + + // See: http://docs.oracle.com/cd/E19957-01/806-3568/ncgTOC.html + // NORMAL NUMBER + if (exponent > 0 && exponent < 255) { + std::cout << "NORMAL NUMBER" << std::endl; + } + + // SUBNORMAL NUMBER + if (exponent == 0 && mantissa != 0) { + std::cout << "SUBNORMAL NUMBER" << std::endl; + } + + // SIGNED ZERO + if (exponent == 0 && mantissa == 0) { + std::cout << "SIGNED ZERO" << std::endl; + } + + // INFINITY + if (exponent == 255 && mantissa == 0) { + std::cout << "INFINITY, SEE SIGN" << std::endl; + } + + // NAN + if (exponent == 255 && mantissa != 0) { + std::cout << "NAN" << std::endl; + } + + std::bitset<8> exponent_bits(exponent); + std::cout << "Exponent, binary value: " << exponent_bits << std::endl; + std::cout << "Exponent, decimal value: " << exponent << std::endl; + std::cout << "Exponent, real value: " << exponent << " - 127 = " << (exponent - 127) << std::endl; + std::cout << std::endl; + + std::bitset<23> mantissa_bits(mantissa); + std::cout << "Mantissa, binary value: " << mantissa_bits << std::endl; + std::cout << "Mantissa, hexadecimal value: "; + std::cout << std::hex << std::uppercase << std::setw(6) << std::setfill('0') << mantissa << std::endl; + std::cout << "Mantissa, binary value (fraction in base 2): 1." << mantissa_bits << std::endl; + std::cout << "Mantissa, decimal value: TODO" << std::endl; + std::cout << std::endl; + + + std::cout << std::endl; + std::cout << "Hexadecimal value (integer representation): "; + std::cout << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << myfloat.i << std::endl; + + return 0; +} + + + + +/*************************************************************************************************** + + + + me@mycomputer:~$ ./floatconverter 0.01 + ****************************************************************************** + + (SIGN) MANTISSA * 2^(EXPONENT-127) (using base 10) + + ****************************************************************************** + + Sign: positive + + Exponent, binary value: 01111000 + Exponent, decimal value: 120 + Exponent, real value: 120 - 127 = -7 + + Mantissa, binary value: 01000111101011100001010 + Mantissa, binary value (fraction in base 2): 1.01000111101011100001010 + Mantissa, decimal value: TODO + + + Hexadecimal value: 3C23D7A + me@mycomputer:~$ echo "ibase=2; 1.01000111101011100001010" | bc + 1.27999997138977050781250 + me@mycomputer:~$ echo "obase=10; scale=10; 1.27999997138977050781250*(2^-7)" | bc + .00999999977648258209228 <------------ closest integer (never 0.01) + + + + +******************************************************************************************************/ -- 2.1.4