Modify how modulo is calculated in Normal and Scientific mode. (#412)

## Fixes #111

> The modulo operator on this calculator gives the result that is different to the most used calculators.

The current `modrate` function is the equivalent of rem(...)/remainder(...), not mod(...)/modulo(...) available in some popular Math apps. 

### Description of the changes:
- rename `modrate` in `remrate` to be more accurate.
- add `modrate`, calculating modulo similarly to Matlab, Bing, Google calculator, Maxima, Wolfram Alpha and Microsoft Excel 
- Add `RationalMath::Mod` using `modrate` as an alternative to `Rational::operator%` using `remrate`
- Add a helper `SIGN` to retrieve the sign of a `Rational`.
- modify `CalcEngine` to use `modrate` in Normal and Scientific mode and `remrate` in Programmer mode.

### How changes were validated:
- manually and unit tests added
This commit is contained in:
Rudy Huyn 2019-04-16 17:17:24 -07:00 committed by Daniel Belcher
parent ad25feda6b
commit 7a7ceb5888
16 changed files with 429 additions and 108 deletions

View file

@ -78,7 +78,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
case IDC_DIV:
case IDC_MOD:
{
int iNumeratorSign = 1, iDenominatorSign = 1, iFinalSign = 1;
int iNumeratorSign = 1, iDenominatorSign = 1;
auto temp = result;
result = rhs;
@ -107,20 +107,30 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
if (operation == IDC_DIV)
{
iFinalSign = iNumeratorSign * iDenominatorSign;
result /= temp;
if (m_fIntegerMode && (iNumeratorSign * iDenominatorSign) == -1)
{
result = -(Integer(result));
}
}
else
{
iFinalSign = iNumeratorSign;
result %= temp;
}
if (m_fIntegerMode)
{
// Programmer mode, use remrat (remainder after division)
result %= temp;
if (m_fIntegerMode && iFinalSign == -1)
{
result = -(Integer(result));
if (iNumeratorSign == -1)
{
result = -(Integer(result));
}
}
else
{
//other modes, use modrat (modulus after division)
result = Mod(result, temp);
}
}
break;
}