C#include <cstdio> int main(int , char *[]){ float f=1; f=0; f=1/f; printf("INF: %e\n",f); f=0; f=0/f; printf("NAN: %e\n",f); f=0; f=-1/f; printf("-INF: %e\n",f); return 0;}
long arg0, arg1=std::numeric_limits<long>::max(), arg2=std::numeric_limits<long>::max(); float res = float(arg1) + float(arg2); if (res >= std::numeric_limits<long>::max()) arg0 = std::numeric_limits<long>::max(); else if (res <= std::numeric_limits<long>::min()) arg0 = std::numeric_limits<long>::min(); else arg0 = long(res);
inline float floatborders(float Value) { if (Value < std::numeric_limits<float>::max()*(-1)) return std::numeric_limits<float>::max()*(-1); if (Value > std::numeric_limits<float>::max()) return std::numeric_limits<float>::max(); if (Value > std::numeric_limits<float>::min()*(-1) && Value > -1 && Value < 0) return std::numeric_limits<float>::min()*(-1); if (Value < std::numeric_limits<float>::min() && Value < 1 && Value > 0) return std::numeric_limits<float>::min(); return Value; }
C++ (Qt)double bad = sqrt(-1.0); // провоцируем nanif (!(bad >= 0) && !(bad < 0)) // кажется бессмысленным, но printf("wrong float %g\n", bad); // поймали nan
C++ (Qt)if (!(bad==bad)) printf("wrong float %g\n", bad);
#include <limits>#include <cmath>class NNumeric{public: inline NNumeric() {this->data._isreal = true; this->data._value = 0; this->data._id = -1; this->data._constvalue = false; this->data._name = "";} inline NNumeric(float Value) {this->data._isreal = true; this->setValue(floatborders(Value)); this->data._id = -1; this->data._constvalue = false; this->data._name = "";} inline NNumeric(long Value) {this->data._isreal = false; this->setValue(Value); this->data._id = -1; this->data._constvalue = false; this->data._name = "";} inline NNumeric(const NNumeric& a) {this->setConstValue(a.data._constvalue); this->setID(a.data._id); this->setName(a.data._name); this->setIsReal(a.data._isreal); this->setValue(a.data._value);} inline float round() {return std::floor(this->Value() + 0.5);} inline float fractional() {return this->Value() < 0 ? this->Value() - std::ceil(this->Value()) : this->Value() - std::floor(this->Value());} inline float integer() {return this->Value() < 0 ? std::ceil(this->Value()) : std::floor(this->Value());} inline int ID() {return this->data._id;} inline void setID(int ID) {this->data._id = ID;} inline bool ConstValue() {return this->data._constvalue;} inline void setConstValue(bool ConstValue) {this->data._constvalue = ConstValue;} inline QString Name() {return this->data._name;} inline void setName(QString Name) {this->data._name = Name;} inline void setIsReal(bool IsReal) {this->data._isreal = IsReal;} //Если ложно, то значение принимается и выдается (при печати числа на экране) // с отсечение дробной части числа и соблюдением границ типа long int. inline bool IsReal() const {return this->data._isreal;} inline void setValue(float Value) { if (!this->data._isreal) { if (Value >= std::numeric_limits<long>::max()) Value = std::numeric_limits<long>::max(); else if (Value <= std::numeric_limits<long>::min()) Value = std::numeric_limits<long>::min(); else Value = long(Value); } this->data._value = Value; } inline float Value() const {return this->data._value;} inline void operator=(const NNumeric& a) {this->setConstValue(a.data._constvalue); this->setID(a.data._id); this->setName(a.data._name); this->setIsReal(a.data._isreal); this->setValue(a.data._value);} inline operator QString() {return QString::number(this->data._value);} inline operator float() {return float(this->data._value);} inline operator double() {return double(this->data._value);} inline operator int() {if (this->Value() < std::numeric_limits<int>::min()) return std::numeric_limits<int>::min(); if (this->Value() > std::numeric_limits<int>::max()) return std::numeric_limits<int>::max(); return int(this->Value());} inline operator long() {if (this->Value() < std::numeric_limits<long>::min()) return std::numeric_limits<long>::min(); if (this->Value() > std::numeric_limits<long>::max()) return std::numeric_limits<long>::max(); return long(this->Value());} inline void operator++(int) {this->data._value + 1 >= std::numeric_limits<long>::max() ? this->data._value = std::numeric_limits<long>::max() : this->data._value++;} inline void operator--(int) {this->data._value - 1 <= std::numeric_limits<long>::min() ? this->data._value = std::numeric_limits<long>::min() : this->data._value--;} inline bool operator==(const NNumeric& a) {return this->data._value == a.Value();} inline bool operator!=(const NNumeric& a) {return this->data._value != a.Value();} inline bool operator&&(const NNumeric& a) {return this->data._value && a.Value();} inline bool operator||(const NNumeric& a) {return this->data._value || a.Value();} inline bool operator<(const NNumeric& a) {return this->data._value < a.Value();} inline bool operator<=(const NNumeric& a) {return this->data._value <= a.Value();} inline bool operator>(const NNumeric& a) {return this->data._value > a.Value();} inline bool operator>=(const NNumeric& a) {return this->data._value >= a.Value();}private: inline float floatborders(float Value) { if (Value < std::numeric_limits<float>::max()*(-1)) return std::numeric_limits<float>::max()*(-1); if (Value > std::numeric_limits<float>::max()) return std::numeric_limits<float>::max(); if (Value > std::numeric_limits<float>::min()*(-1) && Value > -1 && Value < 0) return std::numeric_limits<float>::min()*(-1); if (Value < std::numeric_limits<float>::min() && Value < 1 && Value > 0) return std::numeric_limits<float>::min(); return Value; } struct NData { //если идентификатор равен -1, значит это либо временная переменная, либо константное значение int _id; //константные или временные значения имен не имеют, только переменные. QString _name; float _value; bool _isreal; //это указывает на константное значение bool _constvalue; }; NData data;};
void result::MathematicalOperations(ushort Modifikator){ NNumeric arg0, arg1, arg2; switch (Modifikator) { case 2: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); if (!arg1.IsReal() && !arg2.IsReal()) { float res = float(arg1) + float(arg2); if (res >= std::numeric_limits<long>::max()) arg0 = std::numeric_limits<long>::max(); else if (res <= std::numeric_limits<long>::min()) arg0 = std::numeric_limits<long>::min(); else arg0 = long(res); } else arg0 = float(arg1) + float(arg2); this->StackValue.push(QVariant::fromValue(arg0)); break; case 3: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); if (!arg1.IsReal() && !arg2.IsReal()) { float res = float(arg1) - float(arg2); if (res <= std::numeric_limits<long>::min()) arg0 = std::numeric_limits<long>::min(); else if (res >= std::numeric_limits<long>::max()) arg0 = std::numeric_limits<long>::max(); else arg0 = long(res); } else arg0 = float(arg1) - float(arg2); this->StackValue.push(QVariant::fromValue(arg0)); break; case 4: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); if (!arg1.IsReal() && !arg2.IsReal()) { float res = float(arg1) * float(arg2); if (res >= std::numeric_limits<long>::max()) arg0 = std::numeric_limits<long>::max(); else if (res <= std::numeric_limits<long>::min()) arg0 = std::numeric_limits<long>::min(); else arg0 = long(res); } else arg0 = float(arg1) * float(arg2); this->StackValue.push(QVariant::fromValue(arg0)); break; case 5: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); if (!arg1.IsReal() && !arg2.IsReal()) arg0 = long(arg1) / long(arg2); else arg0 = float(arg1) / float(arg2); this->StackValue.push(QVariant::fromValue(arg0)); break; case 6: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0++; arg0.setID(-1); arg0.setConstValue(false); arg0.setName(""); this->StackValue.push(QVariant::fromValue(arg0)); break; case 7: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0--; arg0.setID(-1); arg0.setConstValue(false); arg0.setName(""); this->StackValue.push(QVariant::fromValue(arg0)); break; case 8: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); arg0 = (ldiv(arg1, arg2)).quot; this->StackValue.push(QVariant::fromValue(arg0)); break; case 9: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); arg0 = (ldiv(arg1, arg2)).rem; this->StackValue.push(QVariant::fromValue(arg0)); break; case 10: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); if (!arg1.IsReal() && !arg2.IsReal()) { float res = std::pow(float(arg1),int(arg2)); if (res > std::numeric_limits<long>::max()) arg0 = std::numeric_limits<long>::max(); else if (res <= std::numeric_limits<long>::min()) arg0 = std::numeric_limits<long>::min(); else arg0 = long(res); } else arg0 = std::pow(float(arg1),float(arg2)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 11: arg0 = (this->StackValue.pop()).value<NNumeric>(); if (!arg0.IsReal()) arg0 = long(std::sqrt(float(arg0))); else arg0 = std::sqrt(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 12: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::fabs(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 13: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); if (!arg1.IsReal() && !arg2.IsReal()) if (long(arg1) < long(arg2)) arg0 = arg1; else arg0 = arg2; else if (float(arg1) < float(arg2)) arg0 = arg1; else arg0 = arg2; arg0.setID(-1); arg0.setConstValue(false); arg0.setName(""); this->StackValue.push(QVariant::fromValue(arg0)); break; case 14: arg2 = (this->StackValue.pop()).value<NNumeric>(); arg1 = (this->StackValue.pop()).value<NNumeric>(); if (!arg1.IsReal() && !arg2.IsReal()) if (long(arg1) > long(arg2)) arg0 = arg1; else arg0 = arg2; else if (float(arg1) > float(arg2)) arg0 = arg1; else arg0 = arg2; arg0.setID(-1); arg0.setConstValue(false); arg0.setName(""); this->StackValue.push(QVariant::fromValue(arg0)); break; case 15: arg0 = (this->StackValue.pop()).value<NNumeric>(); srand ( time(NULL) ); arg0 = long(rand() % long(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 16: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::log10(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 17: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::log(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 18: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::exp(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 19: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::cos(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 20: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::sin(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 21: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::tan(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 22: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = 1.0f/std::tan(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 23: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::acos(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 24: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::asin(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 25: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::atan(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 26: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = 1.0f/std::atan(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 27: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::floor(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 28: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = std::ceil(float(arg0)); this->StackValue.push(QVariant::fromValue(arg0)); break; case 29: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = arg0.round(); this->StackValue.push(QVariant::fromValue(arg0)); break; case 30: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = arg0.fractional(); this->StackValue.push(QVariant::fromValue(arg0)); break; case 31: arg0 = (this->StackValue.pop()).value<NNumeric>(); arg0 = arg0.integer(); this->StackValue.push(QVariant::fromValue(arg0)); break; case 32: srand ( time(NULL) ); arg0 = float(rand() % 1001)/1000.0f; this->StackValue.push(QVariant::fromValue(arg0)); break; }}
Модификатор Комментарий2 +3 -4 *5 /6 ++7 --8 целочисленное деление9 % (остаток от целочисленного деления)10 ^11 квадратный корень12 модуль числа13 минимальное число14 максимальное число15 целочисленный рандом от 0 и до m-116 log1017 ln18 exp19 cos20 sin21 tg22 ctg23 arccos24 arcsin25 arctg26 arcctg27 округление в сторону нуля до целого28 округление в большую сторону до целого29 округление до целого30 выделение дробной части31 отсечение дробной части32 рандом от 0 до 1
C++ (Qt)inline float Value() const {return this->data._value;}
C++ (Qt)inline float Value() const { double d = fabs(this->data._value); bool sign = (this->data._value >= 0.0); if (d > std::numeric_limits<float>::max()) return (sign) ? std::numeric_limits<float>::max() : -std::numeric_limits<float>::max(); if (sign) return (d > std::numeric_limits<float>::min()) ? float(d) : float(0); return (d > std::numeric_limits<float>::min()) ? float(-d) : float(0);}
if (d > std::numeric_limits<float>::max())
C++ (Qt)// static void NNumeric::ValidateOperation( int operation, const NNumeric & arg1, const NNumeric & arg2 ){ if (arg1.Nan()) throw "arg1 is nan"; // стоп, с nan ничего доброго не выйдет if (arg2.Nan()) throw "arg2 is nan"; // для конкретных операций switch (operation) { case NNumeric::operation_divide: if (!arg2.CanBeDivider()) throw "ZeroDivide"; break; ... }}