diff --git a/d06/ex00/Makefile b/d06/ex00/Makefile index b407269..8709f48 100644 --- a/d06/ex00/Makefile +++ b/d06/ex00/Makefile @@ -34,7 +34,8 @@ SRCS = main.cpp \ checkChar.cpp \ checkInt.cpp \ checkFloat.cpp \ - checkDouble.cpp + checkDouble.cpp \ + toTypes.cpp D_HEADERS = . HEADERS = convert.h diff --git a/d06/ex00/a.out b/d06/ex00/a.out new file mode 100755 index 0000000..aa9fe9d Binary files /dev/null and b/d06/ex00/a.out differ diff --git a/d06/ex00/convert b/d06/ex00/convert index 783618f..4a8e4c3 100755 Binary files a/d06/ex00/convert and b/d06/ex00/convert differ diff --git a/d06/ex00/convert.h b/d06/ex00/convert.h index eb32a59..746cc80 100644 --- a/d06/ex00/convert.h +++ b/d06/ex00/convert.h @@ -17,6 +17,14 @@ bool checkInt(std::string str); bool checkFloat(std::string str); bool checkDouble(std::string str); +// templates +// see : https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl +template void toChar(T value); +template void toInt(T value); +template void toFloat(T value); +template void toDouble(T value); +//template void printDot(T value); + #define MAX_INT "2147483647" #define MIN_INT "-2147483648" #define MAX_INT_1 "2147483648" @@ -24,6 +32,7 @@ bool checkDouble(std::string str); #define INT_MAX_LENGTH 10 #define MAX_FLOAT_INT_PRECISION "16777216" #define MAX_FLOAT "340282346638528859811704183484516925440" +#define MIN_FLOAT "-340282346638528859811704183484516925440" #define FLOAT_MAX_LENGTH 39 #define MAX_DOUBLE "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368" #define DOUBLE_MAX_LENGTH 309 @@ -49,6 +58,7 @@ bool checkDouble(std::string str); #define MAX_F_4 "340282346638528859811704183484516925444" #define MAX_F_5 "340282346638528859811704183484516925445" #define MAX_F_6 "340282346638528859811704183484516925446" +#define MAX_F_N "340282346638528897590636046441678635008" #define MIN_DOUBLE "-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368" #define MAX_D__1 "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858367" #define MAX_D__2 "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858366" diff --git a/d06/ex00/main.cpp b/d06/ex00/main.cpp index b831ceb..41b6c1e 100644 --- a/d06/ex00/main.cpp +++ b/d06/ex00/main.cpp @@ -180,6 +180,7 @@ int main(int ac, char **av) { convert(MAX_F_4".0f"); convert(MAX_F_5".0f"); convert(MAX_F_6".0f"); + convert(MAX_F_N".0f"); //double convert("0.0"); convert("-4.2"); @@ -213,6 +214,7 @@ int main(int ac, char **av) { convert(MAX_F_4".0"); convert(MAX_F_5".0"); convert(MAX_F_6".0"); + convert(MAX_F_N".0"); convert(MAX_DOUBLE".0"); convert(MIN_DOUBLE".0"); convert(MAX_D__1".0"); diff --git a/d06/ex00/srcs/checkDouble.cpp b/d06/ex00/srcs/checkDouble.cpp index ae37981..dd06307 100644 --- a/d06/ex00/srcs/checkDouble.cpp +++ b/d06/ex00/srcs/checkDouble.cpp @@ -2,29 +2,11 @@ void fromDouble(double value) { // char - std::cout << std::setw(7) << std::left << "char"; - if (value < 0 || value > std::numeric_limits::max()) - std::cout << B_RED << "impossible" << RESET "\n"; - else if (!isprint(value)) - std::cout << B_RED << "non displayable" << RESET "\n"; - else - std::cout << B_CYAN << static_cast(value) << RESET "\n"; - + toChar(value); // int - std::cout << std::setw(7) << std::left << "int"; - if (value < std::numeric_limits::min() - || value > std::numeric_limits::max() ) - std::cout << B_RED << "impossible" << RESET "\n"; - else - std::cout << B_CYAN << static_cast(value) << RESET "\n"; - + toInt(value); // float - std::cout << std::setw(7) << std::left << "float"; - if (value < std::numeric_limits::min() - || value > std::numeric_limits::max() ) - std::cout << B_RED << "impossible" << RESET "\n"; - else - std::cout << B_CYAN << static_cast(value) << RESET "\n"; + toFloat(value); } bool isDouble(std::string str) { @@ -57,8 +39,11 @@ bool checkDouble(std::string str) { if (!isDouble(str)) return false; - std::istringstream(str) >> d; - std::cout << B_CYAN << d << B_YELLOW " double" RESET "\n"; +// std::istringstream(str) >> d; + d = strtod(str.c_str(), NULL); + std::cout << std::fixed << B_CYAN << d; +// printDot(d); + std::cout << B_YELLOW " double" RESET "\n"; fromDouble(d); return true; diff --git a/d06/ex00/srcs/checkFloat.cpp b/d06/ex00/srcs/checkFloat.cpp index 0db73d9..1ecf40a 100644 --- a/d06/ex00/srcs/checkFloat.cpp +++ b/d06/ex00/srcs/checkFloat.cpp @@ -1,29 +1,15 @@ #include "convert.h" -void fromFloat(float value) { +static void fromFloat(float value) { // char - std::cout << std::setw(7) << std::left << "char"; - if (value < 0 || value > std::numeric_limits::max()) - std::cout << B_RED << "impossible" << RESET "\n"; - else if (!isprint(value)) - std::cout << B_RED << "non displayable" << RESET "\n"; - else - std::cout << B_CYAN << static_cast(value) << RESET "\n"; - + toChar(value); // int - std::cout << std::setw(7) << std::left << "int"; - if (value < std::numeric_limits::min() - || value > std::numeric_limits::max() ) - std::cout << B_RED << "impossible" << RESET "\n"; - else - std::cout << B_CYAN << static_cast(value) << RESET "\n"; - + toInt(value); // double - std::cout << std::setw(7) << std::left << "double"; - std::cout << B_CYAN << static_cast(value) << RESET "\n"; + toDouble(value); } -bool isFloat(std::string str) { +static bool isFloat(std::string str) { size_t l; size_t l2; @@ -53,8 +39,11 @@ bool checkFloat(std::string str) { if (!isFloat(str)) return false; - std::istringstream(str) >> f; - std::cout << B_CYAN << f << B_YELLOW " float" RESET "\n"; +// std::istringstream(str) >> f; + f = strtod(str.c_str(), NULL); + std::cout << std::fixed << B_CYAN << f; +// printDot(f); + std::cout << "f" << B_YELLOW " float" RESET "\n"; fromFloat(f); return true; diff --git a/d06/ex00/srcs/checkInt.cpp b/d06/ex00/srcs/checkInt.cpp index 4585c50..b992a62 100644 --- a/d06/ex00/srcs/checkInt.cpp +++ b/d06/ex00/srcs/checkInt.cpp @@ -2,21 +2,11 @@ void fromInt(int value) { // char - std::cout << std::setw(7) << std::left << "char"; - if (value < 0 || value > std::numeric_limits::max()) - std::cout << B_RED << "impossible" << RESET "\n"; - else if (!isprint(value)) - std::cout << B_RED << "non displayable" << RESET "\n"; - else - std::cout << B_CYAN << static_cast(value) << RESET "\n"; - + toChar(value); // float - std::cout << std::setw(7) << std::left << "float" << B_CYAN - << static_cast(value) << RESET "\n"; - + toFloat(value); // double - std::cout << std::setw(7) << std::left << "double" << B_CYAN - << static_cast(value) << RESET "\n"; + toDouble(value); } bool isInt(std::string str) { diff --git a/d06/ex00/srcs/toTypes.cpp b/d06/ex00/srcs/toTypes.cpp new file mode 100644 index 0000000..180e9d5 --- /dev/null +++ b/d06/ex00/srcs/toTypes.cpp @@ -0,0 +1,90 @@ +#include "convert.h" +#include + +// tried to check for NaN and INF +//static bool is_inf_pos( float a ) { return ( *(((long*)(&a))+1) & 0xFFFFFFFFU ) == 0x7F800000U; } +//static bool is_inf_neg( float a ) { return ( *(((long*)(&a))+1) & 0xFFFFFFFFU ) == 0xFF800000U; } +//static bool is_nan( float a ) { return (( *(((long*)(&a))+1) & 0x7FF80000L ) == 0x7FF800000L); } + +// https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl +template +void toChar(T value) { + std::cout << std::setw(7) << std::left << "char"; +// if (value < 0 || value > std::numeric_limits::max()) + if (!(value >= 0 && value <= std::numeric_limits::max())) + std::cout << B_RED << "impossible" << RESET "\n"; + else if (!isprint(value)) + std::cout << B_RED << "non displayable" << RESET "\n"; + else + std::cout << B_CYAN << static_cast(value) << RESET "\n"; +} + +template +void toInt(T value) { + std::cout << std::setw(7) << std::left << "int"; +// if (value < std::numeric_limits::min() +// || value > std::numeric_limits::max() ) + if (! (value <= std::numeric_limits::max() + && value >= std::numeric_limits::min()) ) + { + std::cout << B_RED << "impossible" << RESET "\n"; + return ; + } + std::cout << B_CYAN << static_cast(value) << RESET "\n"; +} + +template +void toFloat(T value) { + std::cout << std::setw(7) << std::left << "float"; + // tricks to check if is nan and infinity + // see : https://www.jacksondunstan.com/articles/983 + // and : https://stackoverflow.com/questions/2249110/how-do-i-make-a-portable-isnan-isinf-function + if (!((value * 0) != 0)) + // min() ne renvoit que 0, il faut utiliser lowest() (c++11) ou -max() + // https://stackoverflow.com/questions/17070351/why-does-numeric-limitsmin-return-a-negative-value-for-int-but-positive-values + // https://en.cppreference.com/w/cpp/types/numeric_limits/min + if (! (value <= std::numeric_limits::max() + && value >= -(std::numeric_limits::max())) ) + { + std::cout << B_RED << "impossible" << RESET "\n"; + return ; + } + std::cout << B_CYAN << std::fixed << static_cast(value); +// printDot(value); + std::cout << "f" << RESET "\n"; +} + +template +void toDouble(T value) { + std::cout << std::setw(7) << std::left << "double" << B_CYAN + << std::fixed << static_cast(value); +// printDot(value); + std::cout << RESET "\n"; +} + +//template +//void printDot(T value) { +// std::ostringstream ostr; +// ostr << value; +// if (ostr.str().compare("inf") +// && ostr.str().compare("-inf") +// && ostr.str().compare("nan")) +// if ((ostr.str().find('.')) == std::string::npos) +// std::cout << ".0"; +//} + +template void toChar(int); +template void toChar(float); +template void toChar(double); + +template void toInt(float); +template void toInt(double); + +template void toFloat(int); +template void toFloat(double); + +template void toDouble(int); +template void toDouble(float); + +//template void printDot(float); +//template void printDot(double); diff --git a/d06/ex00/test_float.cpp b/d06/ex00/test_float.cpp new file mode 100644 index 0000000..8b2447e --- /dev/null +++ b/d06/ex00/test_float.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +#define MAX_INT 2147483647 +#define MIN_INT -2147483648 +#define MAX_FLOAT 340282346638528859811704183484516925440.0f +#define MIN_FLOAT -340282346638528859811704183484516925440.0f + +void isFloat(double d) { + if (! (d <= std::numeric_limits::max() + && d >= std::numeric_limits::min()) ) + { + std::cout << d << "is outside range of floats\n"; + return ; + } + std::cout << std::fixed << static_cast(d) << "\n"; +} + +int main() { + + double d; + double d2; + + d = std::numeric_limits::max(); + std::cout << std::fixed << d << "\n"; + d2 = std::nextafter(d, DBL_MAX); + std::cout << std::fixed << d2 << "\n"; +// isFloat(MAX_FLOAT); +// d = std::numeric_limits::lowest(); +// std::cout << std::fixed << d << "\n"; +// isFloat(d); + + return 0; +}