From 2fcc6782c4d5dabd88341ffa9024e49d91bb48f4 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Mon, 14 Feb 2022 03:08:13 +0100 Subject: [PATCH] ajout explications transformation float en fixed --- d02/README.md | 308 +++++++++++++++++++++++++++++++++++++++++++++ d02/ex00/Fixed.hpp | 225 --------------------------------- d02/ex01/Fixed.cpp | 51 +++++--- d02/ex01/fixed | Bin 14720 -> 14912 bytes d02/ex01/main.cpp | 3 +- 5 files changed, 344 insertions(+), 243 deletions(-) create mode 100644 d02/README.md diff --git a/d02/README.md b/d02/README.md new file mode 100644 index 0000000..c85ea7b --- /dev/null +++ b/d02/README.md @@ -0,0 +1,308 @@ + +--------------------------------------------------------- +DECIMALE VS BINARY +--------------------------------------------------------- + +11010101 +``` +1*10000000 | (128) | 2^7 | 128 *1 | 0 *2 +1 + 1*1000000 | (64) | 2^6 | + 64 *1 | 1 *2 +1 + 0*100000 | (32) | 2^5 | | 11 *2 + 1*10000 | (16) | 2^4 | + 16 *1 | 110 *2 +1 + 0*1000 | (8) | 2^3 | | 1101 *2 + 1*100 | (4) | 2^2 | + 4 *1 | 11010 *2 +1 + 0*10 | (2) | 2^1 | | 110101 *2 + 1*1 | (1) | 2^0 | + 1 *1 | 1101010 *2 +1 + | ______ | + | 213 | +``` +213 +``` + 2*100 |(1100100)| 10^2 | 1100100 *2 | 0 *10 +2 + 1*10 | (1010)| 10^1 | + 1010 *1 | 2 *10 +1 + 3*1 | (1)| 10^0 | + 1 *3 | 21 *10 +3 + | | | ___________ | 213 + | | | 11010101 | + | + | + 1100100 11001000 1 11010010 | + * 2 + 1010 * 3 + 11 | + _________ _________ ___ _________ | + 11001000 11010010 11 11010101 | + +``` +213 -> 11010101 +``` + 213 -128 = 85 | 213 /2 = 106 r 1 + 85 - 64 = 2 | 106 /2 = 53 r 0 + | 53 /2 = 26 r 1 + 21 - 16 = 5 | 26 /2 = 13 r 0 + | 13 /2 = 6 r 1 + 5 - 4 = 1 | 6 /2 = 3 r 0 + | 3 /2 = 1 r 1 + 1 - 1 = 0 | 1 /2 = 0 r 1 +``` +11010101 -> 213 +``` + | 0*2 + 1 = 1 + | 1*2 + 1 = 3 + | 3*2 = 6 + | 6*2 + 1 = 13 + | 13*2 = 26 + | 26*2 + 1 = 53 + | 53*2 = 106 + | 106*2 + 1 = 213 +``` + + +--------------------------------------------------------- +NEGATIVS INTEGERS +--------------------------------------------------------- + + 5 0101 0 0000 0 0000 0000 0000 0000 0000 0000 0000 0000 + 1010 + 1 1 0001 1 0000 0000 0000 0000 0000 0000 0000 0001 +-5 1011 2 0010 2 0000 0000 0000 0000 0000 0000 0000 0010 + 3 0011 3 0000 0000 0000 0000 0000 0000 0000 0011 + 4 0100 4 0000 0000 0000 0000 0000 0000 0000 0100 + -> 5 0101 5 0000 0000 0000 0000 0000 0000 0000 0101 + 6 0110 6 0000 0000 0000 0000 0000 0000 0000 0110 + 7 0111 7 0000 0000 0000 0000 0000 0000 0000 0111 + ... + 0111 1111 1111 1111 1111 1111 1111 1111 MAXINT + 1000 0000 0000 0000 0000 0000 0000 0000 MININT + ... + 8 1000 -8 1111 1111 1111 1111 1111 1111 1111 1000 + 9 1001 -7 1111 1111 1111 1111 1111 1111 1111 1001 + 10 1010 -6 1111 1111 1111 1111 1111 1111 1111 1010 + -> 11 1011 -5 1111 1111 1111 1111 1111 1111 1111 1011 + 12 1100 -4 1111 1111 1111 1111 1111 1111 1111 1100 + 13 1101 -3 1111 1111 1111 1111 1111 1111 1111 1101 + 14 1110 -2 1111 1111 1111 1111 1111 1111 1111 1110 + 15 1111 -1 1111 1111 1111 1111 1111 1111 1111 1111 + + +--------------------------------------------------------- +FLOATS +--------------------------------------------------------- +https://stackoverflow.com/questions/7644699/how-are-floating-point-numbers-stored-in-memory + + 1.....................23 + 8......1 + seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm meaning +31 0 bit # + signe + exponent + mantis + +1.175494351 * 10^-38 < ... > 3.40282347 * 10^+38 +2x10^-1 = 0.2x10^0 = 0.02x10^1 = 0.2 + +x 00000000 xxxxxxxx xxxxxxxx xxxxxxx special meanings (see bellow) +x 11111111 xxxxxxxx xxxxxxxx xxxxxxx // +x 00000001 xxxxxxxx xxxxxxxx xxxxxxx smallest exponent (-126) +x 01111111 xxxxxxxx xxxxxxxx xxxxxxx 0 is middle exponent (254 / 2 = 127) +x 11111110 xxxxxxxx xxxxxxxx xxxxxxx biggest exponent (+127) + +x 00000000 00000000 00000000 0000000 0 (x can still be + or -) +x 11111111 00000000 00000000 0000000 +/- infinity +x 11111111 xxxxxxxx xxxxxxxx xxxxxx1 NaN (at least one non-zero mantissa digit) +x 00000000 xxxxxxxx xxxxxxxx xxxxxx1 denormalized numbers (same for mantissa) + +--------------------------------------------------------- +CONVERSIONS +--------------------------------------------------------- + +5.75 +``` +5 : + 5 / 2 = 2 -> 1 + 2 / 2 = 1 -> 0 + 1 / 2 = 0 -> 1 +75 : + .75 *2^2 = 2,88 ~= 3 + (*2^x parce que c le moyen dont fait "bouger" la virgule + en base 2 (*10^x) en base 10) + 3 / 2 = 1 -> 1 + 1 / 2 = 0 -> 1 +101.11 = 2^2 + 2^0 + 2^-1 + 2^-2 + = 4 + 1 + 0.5 + 0.25 +``` + +0.875 +``` +.875 * 2^3 = 7 -> 0.111 * 2^3 = 111.0 +7 / 2 = 3 -> 1 +3 / 2 = 1 -> 1 +1 / 1 = 0 -> 1 +0.111 +``` + +0.1875 +``` + -1 1875 +0.1875 = 1.875 * 10^-1 = 01 11101010011 +0.1875 = 0011 +0*2^-1 + 082^-2 + 1*2^-3 + 1*2^-4 + 0 + 0 + .125 + .0625 = .1875 +``` + +-43.625 +``` +-101011.101 +fixed : +1 101011 101 +- + 101011 + 2^5 + 2^3 + 2^1 + 1 + 32 + 8 + 2 + 1 = 43 + 101 + 2^-1 + 2^-3 + .5 + .125 = .625 +``` + +-53.5 --> -110101.1 +``` +[ fixed : ] + 1 110101 1 + - + 110101 + 2^5 + 2^4 + 2^2 + 1 + 32 + 16 + 4 + 1 = 53 + 1 + 2^-1 + .5 = .5 +[ float : ] + -1.101011 * 2^5 + 11.01011 -> 1 + 110.1011 -> 2 + 1101.011 -> 3 + 11010.11 -> 4 + 110101.1 -> 5 + 1 101 101011 + - + 2^2 + 1 + 4 + 1 = 5 + 101011 + ->1101011 +``` + +.85 +``` +.85 * 2 = 1.7 [1] [.7] + .7 * 2 = 1.4 [1] [.4] + .4 * 2 = 0.8 [0] [.8] + .8 * 2 = 1.6 [1] [.6] + .6 * 2 = 1.2 [1] [.2] + .2 * 2 = 0.4 [0] [.4] + .4 * 2 = 0.8 [0] [.8] + .8 * 2 = 1.6 [1] [.6] + .6 * 2 = 1.2 [1] [.2] + .2 * 2 = 0.4 [0] [.4] + .4 * 2 = 0.8 [0] [.8] + .8 * 2 = 1.6 [1] [.6] + .6 * 2 = 1.2 [1] [.2] + .2 * 2 = 0.4 [0] [.4] + .4 * 2 = 0.8 [0] [.8] + .8 * 2 = 1.6 [1] [.6] + .6 * 2 = 1.2 [1] [.2] + .2 * 2 = 0.4 [0] [.4] + .4 * 2 = 0.8 [0] [.8] + .8 * 2 = 1.6 [1] [.6] + .6 * 2 = 1.2 [1] [.2] + .2 * 2 = 0.4 [0] [.4] + .4 * 2 = 0.8 [0] [.8] + ... +-> 11011001100110011001100... + 1 1 0 1 1 0 0 1 1 0 0 1 1 +2^-1 + 2^-2 + 0 + 2^-4 + 2^-5 + 0 + 0 + 2^-8 + 2^-9 + 0 + 0 + 2^-12 + 2^-13 + .5 + .25 + .0625 + .03125 + .00390625 + .001953125 + .000244140625 + .0001220703125 += .8499755859375 +.5 +.75 +.8125 +.84375 +.84765625 +.849609375 +.849853515625 +.8499755859375 +``` + +.453125 +``` +.453125 *2 = 0.90625 [o] [.90625] +.90625 *2 = 1.8125 [1] [.8125] +.8125 *2 = 1.625 [1] [.625] +.625 *2 = 1.25 [1] [.25] +.25 *2 = 0.5 [0] [.5] +.5 *2 = 1 [1] [] +-> .011101 +``` + +--------------------------------------------------------- +REPRESENTATION FLOATS vs INTEGERS +--------------------------------------------------------- + +``` +integer : 1 (1) +floater : 0 01111111 00000000000000000000000 (1) + +integer : 1010 (10) +floater : 0 10000010 01000000000000000000000 (10) + +integer : 1100100 (100) +floater : 0 10000101 10010000000000000000000 (100) + +integer : 1111101000 (1000) +floater : 0 10001000 11110100000000000000000 (1000) + +integer : 00000000000000000000000000000010 (2) +floater : 0 10000000 00000000000000000000000 (2) + + 100010.1 (34.5) +floater : 0 10000100 00010 100000000000000000 (34.5) + + 100010.100011001100110011 (34.55) +floater : 0 10000100 00010 100011001100110011 (34.55) + + 1.0001100110011001101 (1.1) +floater : 0 01111111 00011001100110011001101 (1.1) + + 100010.01 (34.25) +floater : 0 10000100 00010 010000000000000000 (34.25) + + 10101.0011100001010001111 (21.22) +floater : 0 10000011 0101 0011100001010001111 (21.22) + + 110.11001100110011001101 (6.8) +floater : 0 10000001 10 110011001100110011010 (6.8) +``` +--------------------------------------------------------- +FLOATS -> FIXED +--------------------------------------------------------- + +par multiplications binaires : +``` + 100010.01 (34.25) +00100010 01000000 (8768) +00000001 00000000 (256) + + 100010.01000000 34.25 +* 1 00000000.00000000 * 256.00 +----------------------- -------- + 100010 01000000.0 8768.00 + +34.25 * (1 << _frac) +``` +par decalage binaire : +``` +0 10000100 00010 010000000000000000 (34.25) float + 10000100 (132) decaler la virgule de 132 - 127 = 5 + 100010.01 (34.25) fixe + +value = 34.25; +signe = (unsigned int)value; +exponent = ((unsigned int)(value << 1) >> 24) - 127; +fixedd = (unsigned int)(value << 9) >> (32 - exponent - 8); +``` + + diff --git a/d02/ex00/Fixed.hpp b/d02/ex00/Fixed.hpp index cc08f04..9e78866 100644 --- a/d02/ex00/Fixed.hpp +++ b/d02/ex00/Fixed.hpp @@ -26,228 +26,3 @@ private: #endif -// -// /// DECIMALE VS BINARY ////////////////////////////////////// -// -// 11010101 -// -// 1*10000000 | (128) | 2^7 | 128 *1 | 0 *2 +1 -// 1*1000000 | (64) | 2^6 | + 64 *1 | 1 *2 +1 -// 0*100000 | (32) | 2^5 | | 11 *2 -// 1*10000 | (16) | 2^4 | + 16 *1 | 110 *2 +1 -// 0*1000 | (8) | 2^3 | | 1101 *2 -// 1*100 | (4) | 2^2 | + 4 *1 | 11010 *2 +1 -// 0*10 | (2) | 2^1 | | 110101 *2 -// 1*1 | (1) | 2^0 | + 1 *1 | 1101010 *2 +1 -// | ______ | -// | 213 | -// 213 -// -// 2*100 |(1100100)| 10^2 | 1100100 *2 | 0 *10 +2 -// 1*10 | (1010)| 10^1 | + 1010 *1 | 2 *10 +1 -// 3*1 | (1)| 10^0 | + 1 *3 | 21 *10 +3 -// | | | ___________ | 213 -// | | | 11010101 | -// | -// | -// 1100100 11001000 1 11010010 | -// * 2 + 1010 * 3 + 11 | -// _________ _________ ___ _________ | -// 11001000 11010010 11 11010101 | -// -// -// 213 -> 11010101 -// -// 213 -128 = 85 | 213 /2 = 106 r 1 -// 85 - 64 = 2 | 106 /2 = 53 r 0 -// | 53 /2 = 26 r 1 -// 21 - 16 = 5 | 26 /2 = 13 r 0 -// | 13 /2 = 6 r 1 -// 5 - 4 = 1 | 6 /2 = 3 r 0 -// | 3 /2 = 1 r 1 -// 1 - 1 = 0 | 1 /2 = 0 r 1 -// -// 11010101 -> 213 -// -// | 0*2 + 1 = 1 -// | 1*2 + 1 = 3 -// | 3*2 = 6 -// | 6*2 + 1 = 13 -// | 13*2 = 26 -// | 26*2 + 1 = 53 -// | 53*2 = 106 -// | 106*2 + 1 = 213 -// -// -// -// /// NEGATIVS INTEGERS /////////////////////////////////////// -// -// 5 0101 0 0000 0 0000 0000 0000 0000 0000 0000 0000 0000 -// 1010 + 1 1 0001 1 0000 0000 0000 0000 0000 0000 0000 0001 -// -5 1011 2 0010 2 0000 0000 0000 0000 0000 0000 0000 0010 -// 3 0011 3 0000 0000 0000 0000 0000 0000 0000 0011 -// 4 0100 4 0000 0000 0000 0000 0000 0000 0000 0100 -// -> 5 0101 5 0000 0000 0000 0000 0000 0000 0000 0101 -// 6 0110 6 0000 0000 0000 0000 0000 0000 0000 0110 -// 7 0111 7 0000 0000 0000 0000 0000 0000 0000 0111 -// ... -// 0111 1111 1111 1111 1111 1111 1111 1111 MAXINT -// 1000 0000 0000 0000 0000 0000 0000 0000 MININT -// ... -// 8 1000 -8 1111 1111 1111 1111 1111 1111 1111 1000 -// 9 1001 -7 1111 1111 1111 1111 1111 1111 1111 1001 -// 10 1010 -6 1111 1111 1111 1111 1111 1111 1111 1010 -// -> 11 1011 -5 1111 1111 1111 1111 1111 1111 1111 1011 -// 12 1100 -4 1111 1111 1111 1111 1111 1111 1111 1100 -// 13 1101 -3 1111 1111 1111 1111 1111 1111 1111 1101 -// 14 1110 -2 1111 1111 1111 1111 1111 1111 1111 1110 -// 15 1111 -1 1111 1111 1111 1111 1111 1111 1111 1111 -// -// -// /// FLOATS VS FIXED ///////////////////////////////////////// -// -// 1.....................23 -// 8......1 -// seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm meaning -// 31 0 bit # -// -// 2x10^-1 = 0.2x10^0 = 0.02x10^1 = 0.2 -// -// -// ------------------------- -// -// 5.75 -// -// 5 : -// 5 / 2 = 2 -> 1 -// 2 / 2 = 1 -> 0 -// 1 / 2 = 0 -> 1 -// 75 : -// .75 *2^2 = 2,88 ~= 3 -// (*2^x parce que c le moyen dont fait "bouger" la virgule -// en base 2 (*10^x) en base 10) -// 3 / 2 = 1 -> 1 -// 1 / 2 = 0 -> 1 -// 101.11 = 2^2 + 2^0 + 2^-1 + 2^-2 -// = 4 + 1 + 0.5 + 0.25 -// -// ------------------------- -// -// 0.875 -// -// .875 * 2^3 = 7 -> 0.111 * 2^3 = 111.0 -// 7 / 2 = 3 -> 1 -// 3 / 2 = 1 -> 1 -// 1 / 1 = 0 -> 1 -// 0.111 -// -// ------------------------- -// -// 0.1875 -// -1 1875 -// 0.1875 = 1.875 * 10^-1 = 01 11101010011 -// 0.1875 = 0011 -// 0*2^-1 + 082^-2 + 1*2^-3 + 1*2^-4 -// 0 + 0 + .125 + .0625 = .1875 -// -// -// ------------------------- -// -// -43.625 -// -// -101011.101 -// fixed : -// 1 101011 101 -// - -// 101011 -// 2^5 + 2^3 + 2^1 + 1 -// 32 + 8 + 2 + 1 = 43 -// 101 -// 2^-1 + 2^-3 -// .5 + .125 = .625 -// -// -// ------------------------- -// -// -53.5 --> -110101.1 -// -// [ fixed : ] -// 1 110101 1 -// - -// 110101 -// 2^5 + 2^4 + 2^2 + 1 -// 32 + 16 + 4 + 1 = 53 -// 1 -// 2^-1 -// .5 = .5 -// [ float : ] -// -1.101011 * 2^5 -// 11.01011 -> 1 -// 110.1011 -> 2 -// 1101.011 -> 3 -// 11010.11 -> 4 -// 110101.1 -> 5 -// 1 101 101011 -// - -// 2^2 + 1 -// 4 + 1 = 5 -// 101011 -// ->1101011 -// -// -// ------------------------- -// -// .85 -// -// .85 * 2 = 1.7 [1] [.7] -// .7 * 2 = 1.4 [1] [.4] -// .4 * 2 = 0.8 [0] [.8] -// .8 * 2 = 1.6 [1] [.6] -// .6 * 2 = 1.2 [1] [.2] -// .2 * 2 = 0.4 [0] [.4] -// .4 * 2 = 0.8 [0] [.8] -// .8 * 2 = 1.6 [1] [.6] -// .6 * 2 = 1.2 [1] [.2] -// .2 * 2 = 0.4 [0] [.4] -// .4 * 2 = 0.8 [0] [.8] -// .8 * 2 = 1.6 [1] [.6] -// .6 * 2 = 1.2 [1] [.2] -// .2 * 2 = 0.4 [0] [.4] -// .4 * 2 = 0.8 [0] [.8] -// .8 * 2 = 1.6 [1] [.6] -// .6 * 2 = 1.2 [1] [.2] -// .2 * 2 = 0.4 [0] [.4] -// .4 * 2 = 0.8 [0] [.8] -// .8 * 2 = 1.6 [1] [.6] -// .6 * 2 = 1.2 [1] [.2] -// .2 * 2 = 0.4 [0] [.4] -// .4 * 2 = 0.8 [0] [.8] -// ... -// -> 11011001100110011001100... -// 1 1 0 1 1 0 0 1 1 0 0 1 1 -// 2^-1 + 2^-2 + 0 + 2^-4 + 2^-5 + 0 + 0 + 2^-8 + 2^-9 + 0 + 0 + 2^-12 + 2^-13 -// .5 + .25 + .0625 + .03125 + .00390625 + .001953125 + .000244140625 + .0001220703125 -// = .8499755859375 -// .5 -// .75 -// .8125 -// .84375 -// .84765625 -// .849609375 -// .849853515625 -// .8499755859375 -// -// -// ------------------------- -// -// .453125 -// -// .453125 *2 = 0.90625 [o] [.90625] -// .90625 *2 = 1.8125 [1] [.8125] -// .8125 *2 = 1.625 [1] [.625] -// .625 *2 = 1.25 [1] [.25] -// .25 *2 = 0.5 [0] [.5] -// .5 *2 = 1 [1] [] -// -> .011101 -// -// diff --git a/d02/ex01/Fixed.cpp b/d02/ex01/Fixed.cpp index 00567bd..63a5fa8 100644 --- a/d02/ex01/Fixed.cpp +++ b/d02/ex01/Fixed.cpp @@ -1,22 +1,40 @@ #include "Fixed.hpp" /* - * function to print integers in binary + * functions to print numbers in binary + * for the float, found help from stackoverflow : + * https://stackoverflow.com/questions/474007/floating-point-to-binary-valuec */ -void printBits(std::string before, unsigned int num) +std::string printBitsInt(int num) { int i = 0; - std::cout << before; - for (unsigned int mask = 1U << 31; mask; mask = mask >> 1) + std::cout << " "; + for (unsigned int mask = 1U << (sizeof(int) *8 -1); mask; mask >>= 1) { std::cout << ((num & mask) != 0); i++; - if (i % 8 == 0) +// if (i % 8 == 0 && i < 32) + if (i == 1 || i == 9 || i == 24) std::cout << ' '; } - std::cout << "(" << (signed int)num << ")" << '\n'; + return ""; +} + +std::string printBitsFloat(float num) +{ + int *p = (int *)# + int i = 0; + + for (unsigned int mask = 1U << (sizeof(float) *8 -1); mask; mask >>= 1) + { + std::cout << ((*p & mask) != 0); + i++; + if (i == 1 || i == 9) + std::cout << ' '; + } + return ""; } /* @@ -37,18 +55,18 @@ int const Fixed::_max = -1U >> (_frac +1); */ Fixed::Fixed() : _value(0) { - std::cout << "Default constructor called" << '\n'; +// std::cout << "Default constructor called" << '\n'; return; } Fixed::Fixed(Fixed const & src) { - std::cout << "Copy constructor called" << '\n'; +// std::cout << "Copy constructor called" << '\n'; *this = src; return; } Fixed::~Fixed( void ) { - std::cout << "Destructor called" << '\n'; +// std::cout << "Destructor called" << '\n'; return; } @@ -57,27 +75,26 @@ Fixed::~Fixed( void ) { */ Fixed::Fixed(int integer) { - std::cout << "Int constructor called" << '\n'; +// std::cout << "Int constructor called" << '\n'; if (integer < ~this->_max || integer > this->_max) { std::cout << "error: integer out of range" << '\n'; return; } - printBits("integer : ", integer); + std::cout << "integer : " << printBitsInt(integer) << " (" << integer << ")\n"; this->_value = integer << this->_frac; - printBits("integer : ", this->_value); } Fixed::Fixed(float const floater) { - std::cout << "Float constructor called" << '\n'; +// std::cout << "Float constructor called" << '\n'; if (floater < ~this->_max || floater > this->_max) { std::cout << "error: float out of range" << '\n'; return; } - + std::cout << "floater : " << printBitsFloat(floater) << " (" << floater << ")\n"; } @@ -86,7 +103,7 @@ Fixed::Fixed(float const floater) { */ Fixed & Fixed::operator=( Fixed const & rhs ) { - std::cout << "Copy assignment operator called" << '\n'; +// std::cout << "Copy assignment operator called" << '\n'; if ( this != &rhs ) this->_value = rhs.getRawBits(); @@ -98,7 +115,7 @@ Fixed & Fixed::operator=( Fixed const & rhs ) { */ int Fixed::getRawBits( void ) const { - std::cout << "getRawBits member function called" << '\n'; +// std::cout << "getRawBits member function called" << '\n'; return this->_value; } @@ -110,3 +127,5 @@ void Fixed::toFloat( void ) const {} int Fixed::toInt( void ) const { return 0; } + + diff --git a/d02/ex01/fixed b/d02/ex01/fixed index 7a4f4017406a186ef6c789a0be21e61d461de461..e147d71d8ce47e2e67c4aadf140c55419d201665 100755 GIT binary patch literal 14912 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 delta 5055 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 R;u1fftXrk5