kcalc
knumber.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cmath>
00022 #include <cstdio>
00023
00024 #include <config-kcalc.h>
00025
00026 #include <QRegExp>
00027
00028 #include "knumber_priv.h"
00029 #include "knumber.h"
00030
00031 using namespace std;
00032
00033 KNumber const KNumber::Zero(0);
00034 KNumber const KNumber::One(1);
00035 KNumber const KNumber::MinusOne(-1);
00036 KNumber const KNumber::Pi("3.141592653589793238462643383279502884197169"
00037 "39937510582097494459230781640628620899862803"
00038 "4825342117068");
00039 KNumber const KNumber::Euler("2.718281828459045235360287471352662497757"
00040 "24709369995957496696762772407663035354759"
00041 "4571382178525166427");
00042 KNumber const KNumber::NotDefined("nan");
00043
00044 bool KNumber::_float_output = false;
00045 bool KNumber::_fraction_input = false;
00046 bool KNumber::_splitoffinteger_output = false;
00047
00048 #ifndef HAVE_FUNC_ISINF
00049
00050 #ifdef HAVE_IEEEFP_H
00051 #include <ieeefp.h>
00052 #else
00053 #include <math.h>
00054 #endif
00055
00056 #define isinf(x) (!finite(x) && x == x)
00057 #endif
00058
00059 KNumber::KNumber(qint32 num)
00060 {
00061 _num = new _knuminteger(num);
00062 }
00063
00064 KNumber::KNumber(quint32 num)
00065 {
00066 _num = new _knuminteger(num);
00067 }
00068
00069 KNumber::KNumber(quint64 num)
00070 {
00071 _num = new _knuminteger(num);
00072 }
00073
00074 KNumber::KNumber(double num)
00075 {
00076 if ( isinf(num) ) _num = new _knumerror( _knumber::Infinity );
00077 else if ( isnan(num) ) _num = new _knumerror( _knumber::UndefinedNumber );
00078 else _num = new _knumfloat(num);
00079
00080 }
00081
00082 KNumber::KNumber(KNumber const & num)
00083 {
00084 switch(num.type()) {
00085 case SpecialType:
00086 _num = new _knumerror(*(num._num));
00087 return;
00088 case IntegerType:
00089 _num = new _knuminteger(*(num._num));
00090 return;
00091 case FractionType:
00092 _num = new _knumfraction(*(num._num));
00093 return;
00094 case FloatType:
00095 _num = new _knumfloat(*(num._num));
00096 return;
00097 };
00098 }
00099
00100 KNumber::KNumber(QString const & num)
00101 {
00102 if (QRegExp("^(inf|-inf|nan)$").exactMatch(num))
00103 _num = new _knumerror(num);
00104 else if (QRegExp("^[+-]?\\d+$").exactMatch(num))
00105 _num = new _knuminteger(num);
00106 else if (QRegExp("^[+-]?\\d+/\\d+$").exactMatch(num)) {
00107 _num = new _knumfraction(num);
00108 simplifyRational();
00109 }
00110 else if (QRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num))
00111 if (_fraction_input == true) {
00112 _num = new _knumfraction(num);
00113 simplifyRational();
00114 } else
00115 _num = new _knumfloat(num);
00116 else
00117 _num = new _knumerror("nan");
00118 }
00119
00120 KNumber::~KNumber()
00121 {
00122 delete _num;
00123 }
00124
00125 KNumber::NumType KNumber::type(void) const
00126 {
00127 if(dynamic_cast<_knumerror *>(_num))
00128 return SpecialType;
00129 if(dynamic_cast<_knuminteger *>(_num))
00130 return IntegerType;
00131 if(dynamic_cast<_knumfraction *>(_num))
00132 return FractionType;
00133 if(dynamic_cast<_knumfloat *>(_num))
00134 return FloatType;
00135
00136 return SpecialType;
00137 }
00138
00139
00140
00141
00142
00143 void KNumber::simplifyRational(void)
00144 {
00145 if (type() != FractionType)
00146 return;
00147
00148 _knumfraction *tmp_num = dynamic_cast<_knumfraction *>(_num);
00149
00150 if (tmp_num->isInteger()) {
00151 _knumber *tmp_num2 = tmp_num->intPart();
00152 delete tmp_num;
00153 _num = tmp_num2;
00154 }
00155
00156 }
00157
00158
00159 KNumber const & KNumber::operator=(KNumber const & num)
00160 {
00161 if (this == & num)
00162 return *this;
00163
00164 delete _num;
00165
00166 switch(num.type()) {
00167 case SpecialType:
00168 _num = new _knumerror();
00169 break;
00170 case IntegerType:
00171 _num = new _knuminteger();
00172 break;
00173 case FractionType:
00174 _num = new _knumfraction();
00175 break;
00176 case FloatType:
00177 _num = new _knumfloat();
00178 break;
00179 };
00180
00181 _num->copy(*(num._num));
00182
00183 return *this;
00184 }
00185
00186 KNumber & KNumber::operator +=(KNumber const &arg)
00187 {
00188 KNumber tmp_num = *this + arg;
00189
00190 delete _num;
00191
00192 switch(tmp_num.type()) {
00193 case SpecialType:
00194 _num = new _knumerror();
00195 break;
00196 case IntegerType:
00197 _num = new _knuminteger();
00198 break;
00199 case FractionType:
00200 _num = new _knumfraction();
00201 break;
00202 case FloatType:
00203 _num = new _knumfloat();
00204 break;
00205 };
00206
00207 _num->copy(*(tmp_num._num));
00208
00209 return *this;
00210 }
00211
00212 KNumber & KNumber::operator -=(KNumber const &arg)
00213 {
00214 KNumber tmp_num = *this - arg;
00215
00216 delete _num;
00217
00218 switch(tmp_num.type()) {
00219 case SpecialType:
00220 _num = new _knumerror();
00221 break;
00222 case IntegerType:
00223 _num = new _knuminteger();
00224 break;
00225 case FractionType:
00226 _num = new _knumfraction();
00227 break;
00228 case FloatType:
00229 _num = new _knumfloat();
00230 break;
00231 };
00232
00233 _num->copy(*(tmp_num._num));
00234
00235 return *this;
00236 }
00237
00238
00239 static void _inc_by_one(QString &str, int position)
00240 {
00241 for (int i = position; i >= 0; i--)
00242 {
00243 char last_char = str[i].toLatin1();
00244 switch(last_char)
00245 {
00246 case '0':
00247 str[i] = '1';
00248 break;
00249 case '1':
00250 str[i] = '2';
00251 break;
00252 case '2':
00253 str[i] = '3';
00254 break;
00255 case '3':
00256 str[i] = '4';
00257 break;
00258 case '4':
00259 str[i] = '5';
00260 break;
00261 case '5':
00262 str[i] = '6';
00263 break;
00264 case '6':
00265 str[i] = '7';
00266 break;
00267 case '7':
00268 str[i] = '8';
00269 break;
00270 case '8':
00271 str[i] = '9';
00272 break;
00273 case '9':
00274 str[i] = '0';
00275 if (i == 0) str.prepend('1');
00276 continue;
00277 case '.':
00278 continue;
00279 }
00280 break;
00281 }
00282 }
00283
00284
00285 static void _round(QString &str, int precision)
00286 {
00287 int decimalSymbolPos = str.indexOf('.');
00288
00289 if (decimalSymbolPos == -1)
00290 if (precision == 0) return;
00291 else if (precision > 0)
00292 {
00293 str.append('.');
00294 decimalSymbolPos = str.length() - 1;
00295 }
00296
00297
00298 str.append(QString().fill('0', precision));
00299
00300
00301 char last_char = str[decimalSymbolPos + precision + 1].toLatin1();
00302 switch (last_char)
00303 {
00304 case '0':
00305 case '1':
00306 case '2':
00307 case '3':
00308 case '4':
00309
00310 break;
00311 case '5':
00312 case '6':
00313 case '7':
00314 case '8':
00315 case '9':
00316
00317 _inc_by_one(str, decimalSymbolPos + precision);
00318 break;
00319 default:
00320 break;
00321 }
00322
00323 decimalSymbolPos = str.indexOf('.');
00324 str.truncate(decimalSymbolPos + precision + 1);
00325
00326
00327 if (precision == 0) str = str.section('.', 0, 0);
00328 }
00329
00330 static QString roundNumber(const QString &numStr, int precision)
00331 {
00332 QString tmpString = numStr;
00333 if (precision < 0 ||
00334 ! QRegExp("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$").exactMatch(tmpString))
00335 return numStr;
00336
00337
00338
00339 bool neg = (tmpString[0] == '-');
00340 if (neg || tmpString[0] == '+') tmpString.remove(0, 1);
00341
00342
00343
00344 QString mantString = tmpString.section('e', 0, 0,
00345 QString::SectionCaseInsensitiveSeps);
00346 QString expString = tmpString.section('e', 1, 1,
00347 QString::SectionCaseInsensitiveSeps |
00348 QString::SectionIncludeLeadingSep);
00349 if (expString.length() == 1) expString = QString();
00350
00351
00352 _round(mantString, precision);
00353
00354 if(neg) mantString.prepend('-');
00355
00356 return mantString + expString;
00357 }
00358
00359
00360 QString const KNumber::toQString(int width, int prec) const
00361 {
00362 QString tmp_str;
00363
00364 if (*this == Zero)
00365 return "0";
00366 switch (type()) {
00367 case IntegerType:
00368 if (width > 0) {
00369 bool tmp_bool = _fraction_input;
00370 _fraction_input = false;
00371 tmp_str = (KNumber(1.0)*(*this)).toQString(width, -1);
00372 _fraction_input = tmp_bool;
00373 } else
00374 tmp_str = QString(_num->ascii());
00375 break;
00376 case FractionType:
00377 if (_float_output) {
00378 bool tmp_bool = _fraction_input;
00379 _fraction_input = false;
00380 tmp_str = (KNumber(1.0)*(*this)).toQString(width, -1);
00381 _fraction_input = tmp_bool;
00382 } else {
00383 if(_splitoffinteger_output) {
00384
00385 KNumber int_part = this->integerPart();
00386 if (int_part == Zero)
00387 tmp_str = QString(_num->ascii());
00388 else if (int_part < Zero)
00389 tmp_str = int_part.toQString() + ' ' + (int_part - *this)._num->ascii();
00390 else
00391 tmp_str = int_part.toQString() + ' ' + (*this - int_part)._num->ascii();
00392 } else
00393 tmp_str = QString(_num->ascii());
00394
00395 if (width > 0 && tmp_str.length() > width) {
00396
00397 bool tmp_bool = _fraction_input;
00398 _fraction_input = false;
00399 tmp_str = (KNumber(1.0)*(*this)).toQString(width, -1);
00400 _fraction_input = tmp_bool;
00401 }
00402 }
00403
00404 break;
00405 case FloatType:
00406 if (width > 0)
00407 tmp_str = QString(_num->ascii(width));
00408 else
00409
00410 tmp_str = QString(_num->ascii(3*mpf_get_default_prec()/10));
00411 break;
00412 default:
00413 return QString(_num->ascii());
00414 }
00415
00416 if (prec >= 0)
00417 return roundNumber(tmp_str, prec);
00418 else
00419 return tmp_str;
00420 }
00421
00422 void KNumber::setDefaultFloatOutput(bool flag)
00423 {
00424 _float_output = flag;
00425 }
00426
00427 void KNumber::setDefaultFractionalInput(bool flag)
00428 {
00429 _fraction_input = flag;
00430 }
00431
00432 void KNumber::setSplitoffIntegerForFractionOutput(bool flag)
00433 {
00434 _splitoffinteger_output = flag;
00435 }
00436
00437 void KNumber::setDefaultFloatPrecision(unsigned int prec)
00438 {
00439
00440 unsigned long int bin_prec = static_cast<unsigned long int>
00441 (double(prec) * M_LN10 / M_LN2 + 1);
00442
00443 mpf_set_default_prec(bin_prec);
00444 }
00445
00446 KNumber const KNumber::abs(void) const
00447 {
00448 KNumber tmp_num;
00449 delete tmp_num._num;
00450
00451 tmp_num._num = _num->abs();
00452
00453 return tmp_num;
00454 }
00455
00456 KNumber const KNumber::cbrt(void) const
00457 {
00458 KNumber tmp_num;
00459 delete tmp_num._num;
00460
00461 tmp_num._num = _num->cbrt();
00462
00463 return tmp_num;
00464 }
00465
00466 KNumber const KNumber::sqrt(void) const
00467 {
00468 KNumber tmp_num;
00469 delete tmp_num._num;
00470
00471 tmp_num._num = _num->sqrt();
00472
00473 return tmp_num;
00474 }
00475
00476 KNumber const KNumber::integerPart(void) const
00477 {
00478 KNumber tmp_num;
00479 delete tmp_num._num;
00480 tmp_num._num = _num->intPart();
00481
00482 return tmp_num;
00483 }
00484
00485 KNumber const KNumber::power(KNumber const &exp) const
00486 {
00487 if (*this == Zero) {
00488 if(exp == Zero)
00489 return KNumber("nan");
00490 else if (exp < Zero)
00491 return KNumber("inf");
00492 else
00493 return KNumber(0);
00494 }
00495
00496 if (exp == Zero) {
00497 if (*this != Zero)
00498 return One;
00499 else
00500 return KNumber("nan");
00501 }
00502 else if (exp < Zero) {
00503 KNumber tmp_num;
00504 KNumber tmp_num2 = -exp;
00505 delete tmp_num._num;
00506 tmp_num._num = _num->power(*(tmp_num2._num));
00507
00508 return One/tmp_num;
00509 }
00510 else {
00511 KNumber tmp_num;
00512 delete tmp_num._num;
00513 tmp_num._num = _num->power(*(exp._num));
00514
00515 return tmp_num;
00516 }
00517
00518 }
00519
00520 KNumber const KNumber::operator-(void) const
00521 {
00522 KNumber tmp_num;
00523 delete tmp_num._num;
00524
00525 tmp_num._num = _num->change_sign();
00526
00527 return tmp_num;
00528 }
00529
00530 KNumber const KNumber::operator+(KNumber const & arg2) const
00531 {
00532 KNumber tmp_num;
00533 delete tmp_num._num;
00534
00535 tmp_num._num = _num->add(*arg2._num);
00536
00537 tmp_num.simplifyRational();
00538
00539 return tmp_num;
00540 }
00541
00542 KNumber const KNumber::operator-(KNumber const & arg2) const
00543 {
00544 return *this + (-arg2);
00545 }
00546
00547 KNumber const KNumber::operator*(KNumber const & arg2) const
00548 {
00549 KNumber tmp_num;
00550 delete tmp_num._num;
00551
00552 tmp_num._num = _num->multiply(*arg2._num);
00553
00554 tmp_num.simplifyRational();
00555
00556 return tmp_num;
00557 }
00558
00559 KNumber const KNumber::operator/(KNumber const & arg2) const
00560 {
00561 KNumber tmp_num;
00562 delete tmp_num._num;
00563
00564 tmp_num._num = _num->divide(*arg2._num);
00565
00566 tmp_num.simplifyRational();
00567
00568 return tmp_num;
00569 }
00570
00571
00572 KNumber const KNumber::operator%(KNumber const & arg2) const
00573 {
00574 if (type() != IntegerType || arg2.type() != IntegerType)
00575 return Zero;
00576
00577 KNumber tmp_num;
00578 delete tmp_num._num;
00579
00580 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00581 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
00582
00583 tmp_num._num = tmp_arg1->mod(*tmp_arg2);
00584
00585 return tmp_num;
00586 }
00587
00588 KNumber const KNumber::operator&(KNumber const & arg2) const
00589 {
00590 if (type() != IntegerType || arg2.type() != IntegerType)
00591 return Zero;
00592
00593 KNumber tmp_num;
00594 delete tmp_num._num;
00595
00596 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00597 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
00598
00599 tmp_num._num = tmp_arg1->intAnd(*tmp_arg2);
00600
00601 return tmp_num;
00602
00603 }
00604
00605 KNumber const KNumber::operator|(KNumber const & arg2) const
00606 {
00607 if (type() != IntegerType || arg2.type() != IntegerType)
00608 return Zero;
00609
00610 KNumber tmp_num;
00611 delete tmp_num._num;
00612
00613 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00614 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
00615
00616 tmp_num._num = tmp_arg1->intOr(*tmp_arg2);
00617
00618 return tmp_num;
00619 }
00620
00621
00622 KNumber const KNumber::operator<<(KNumber const & arg2) const
00623 {
00624 if (type() != IntegerType || arg2.type() != IntegerType)
00625 return KNumber("nan");
00626
00627 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00628 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
00629
00630 KNumber tmp_num;
00631 delete tmp_num._num;
00632 tmp_num._num = tmp_arg1->shift(*tmp_arg2);
00633
00634 return tmp_num;
00635 }
00636
00637 KNumber const KNumber::operator>>(KNumber const & arg2) const
00638 {
00639 if (type() != IntegerType || arg2.type() != IntegerType)
00640 return KNumber("nan");
00641
00642 KNumber tmp_num = -arg2;
00643
00644 _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
00645 _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(tmp_num._num);
00646
00647 KNumber tmp_num2;
00648 delete tmp_num2._num;
00649 tmp_num2._num = tmp_arg1->shift(*tmp_arg2);
00650
00651 return tmp_num2;
00652 }
00653
00654
00655
00656 KNumber::operator bool(void) const
00657 {
00658 if (*this == Zero)
00659 return false;
00660 return true;
00661 }
00662
00663 KNumber::operator qint32(void) const
00664 {
00665 return static_cast<long int>(*_num);
00666 }
00667
00668 KNumber::operator quint32(void) const
00669 {
00670 return static_cast<unsigned long int>(*_num);
00671 }
00672
00673 KNumber::operator quint64(void) const
00674 {
00675 #if SIZEOF_UNSIGNED_LONG == 8
00676 return static_cast<unsigned long int>(*_num);
00677 #elif SIZEOF_UNSIGNED_LONG == 4
00678 KNumber tmp_num1 = this->abs().integerPart();
00679 quint64 tmp_num2 = static_cast<quint32>(tmp_num1) +
00680 (static_cast<quint64>(static_cast<quint32>(tmp_num1 >> KNumber("32"))) << 32) ;
00681
00682 #ifdef __GNUC__
00683 #warning "the cast operator from KNumber to quint64 is probably buggy, when a sign is involved"
00684 #endif
00685 if (*this > KNumber(0))
00686 return tmp_num2;
00687 else
00688 return static_cast<quint64> (- static_cast<qint64>(tmp_num2));
00689 #else
00690 #error "SIZEOF_UNSIGNED_LONG is a unhandled case"
00691 #endif
00692 }
00693
00694 KNumber::operator double(void) const
00695 {
00696 return static_cast<double>(*_num);
00697 }
00698
00699 int const KNumber::compare(KNumber const & arg2) const
00700 {
00701 return _num->compare(*arg2._num);
00702 }