Ignore casing in hexadecimal numbers

This commit is contained in:
Carsten Sonne Larsen 2018-08-05 21:44:15 +02:00
parent 2a7b341c71
commit 4c6ae02156
2 changed files with 126 additions and 38 deletions

View File

@ -40,18 +40,28 @@
PositionalNumeralSystem::PositionalNumeralSystem( PositionalNumeralSystem::PositionalNumeralSystem(
unsigned int base, unsigned int base,
unsigned int digits, unsigned int digits,
const char fractionPoint) : base(base * 1.0), digits(digits) const char fractionPoint) : digits(digits)
{ {
this->fractionPoint = fractionPoint; this->fractionPoint = fractionPoint;
this->baseInteger = base;
this->baseDouble = base * 1.0;
this->maxNumeric = (base > 10 ? 10 : base) + '0' - 1;
this->maxAlphaLower = base > 10 ? base + 'a' - 11 : 0;
this->maxAlphaUpper = base > 10 ? base + 'A' - 11 : 0;
} }
PositionalNumeralSystem::~PositionalNumeralSystem() PositionalNumeralSystem::~PositionalNumeralSystem()
{ {
} }
bool PositionalNumeralSystem::IsDigit(char *digit)
{
return true;
}
const char *PositionalNumeralSystem::GetName() const char *PositionalNumeralSystem::GetName()
{ {
switch (static_cast<int>(base)) switch (baseInteger)
{ {
case 2: case 2:
return "binary"; return "binary";
@ -64,7 +74,7 @@ const char *PositionalNumeralSystem::GetName()
} }
const char *text = "base "; const char *text = "base ";
Number *n = new RealNumber(base); Number *n = new RealNumber(baseInteger);
NumeralSystem *ns = new DecimalSystem(2); NumeralSystem *ns = new DecimalSystem(2);
const char *numtext = ns->GetText(n); const char *numtext = ns->GetText(n);
@ -211,21 +221,21 @@ const char *PositionalNumeralSystem::GetText(double number) const
dnumber = -dnumber; dnumber = -dnumber;
} }
double expbor = log2p(base, dnumber); double expbor = log2p(baseDouble, dnumber);
double expacc = expbor > 0.0 ? 4e-14 : -1e-15; double expacc = expbor > 0.0 ? 4e-14 : -1e-15;
double expborder = trunc(expbor + expacc); double expborder = trunc(expbor + expacc);
int exponent = 0; int exponent = 0;
double rounding; double rounding;
double bordermax = trunc(9.0 * 10 / base); double bordermax = trunc(9.0 * 10 / baseDouble);
double bordermin = trunc(-8.0 * 10 / base); double bordermin = trunc(-8.0 * 10 / baseDouble);
// Find exponent // Find exponent
if (expborder >= bordermax || expborder <= bordermin) if (expborder >= bordermax || expborder <= bordermin)
{ {
double dexp = trunc(log2p(base, dnumber) + expacc); double dexp = trunc(log2p(baseDouble, dnumber) + expacc);
dnumber = dnumber * pow(base, -dexp); dnumber = dnumber * pow(baseDouble, -dexp);
// pow is inaccurate on small and large numbers // pow is inaccurate on small and large numbers
if (dexp > 15 || dexp < -15) if (dexp > 15 || dexp < -15)
@ -237,7 +247,7 @@ const char *PositionalNumeralSystem::GetText(double number) const
if (dnumber < 1.0) if (dnumber < 1.0)
{ {
dexp--; dexp--;
dnumber *= base; dnumber *= baseDouble;
} }
exponent = static_cast<int>(dexp); exponent = static_cast<int>(dexp);
@ -246,7 +256,7 @@ const char *PositionalNumeralSystem::GetText(double number) const
else else
{ {
double acc = exponent > 0 ? 15 : -15; double acc = exponent > 0 ? 15 : -15;
rounding = pow(base, exponent + acc); rounding = pow(baseDouble, exponent + acc);
} }
int digitout; int digitout;
@ -260,8 +270,8 @@ const char *PositionalNumeralSystem::GetText(double number) const
{ {
buf->Append(fractionPoint); buf->Append(fractionPoint);
double fraction = fabs(round((dnumber - intvalue) * pow(base, fragdigits))); double fraction = fabs(round((dnumber - intvalue) * pow(baseDouble, fragdigits)));
double temp1 = log2p(base, fraction); double temp1 = log2p(baseDouble, fraction);
FloatUnion64 temp2; FloatUnion64 temp2;
temp2.floatingPoint = temp1; temp2.floatingPoint = temp1;
bool fin = !temp2.IsInf(); bool fin = !temp2.IsInf();
@ -274,7 +284,7 @@ const char *PositionalNumeralSystem::GetText(double number) const
buf->Append('0'); buf->Append('0');
} }
intvalue = static_cast<int64_t>(trunc(fraction * base) / base); intvalue = static_cast<int64_t>(trunc(fraction * baseDouble) / baseDouble);
IntegerToBuffer(intvalue, fragdigits, &digitout); IntegerToBuffer(intvalue, fragdigits, &digitout);
// Remove trailing zeros // Remove trailing zeros
@ -313,9 +323,9 @@ void PositionalNumeralSystem::IntegerToBuffer(double value, unsigned int digits,
do do
{ {
count++; count++;
unsigned int intremainder = static_cast<unsigned int>(trunc(fmod(value, base))); unsigned int intremainder = static_cast<unsigned int>(trunc(fmod(value, baseDouble)));
*chars++ = alphaNumerics[intremainder]; *chars++ = alphaNumerics[intremainder];
value /= base; value /= baseDouble;
} while (value >= 1.0); } while (value >= 1.0);
unsigned int n = count; unsigned int n = count;
@ -339,50 +349,99 @@ void PositionalNumeralSystem::IntegerToBuffer(double value, unsigned int digits,
Number *PositionalNumeralSystem::Parse(const char *text, unsigned int *length, char **end) Number *PositionalNumeralSystem::Parse(const char *text, unsigned int *length, char **end)
{ {
unsigned int intbase = static_cast<unsigned int>(base);
char maxNumeric = (intbase > 10 ? 10 : intbase) + '0' - 1;
char maxAlpha = intbase > 10 ? intbase + 'A' - 11 : 0;
unsigned int pos = 0; unsigned int pos = 0;
double integer = 0; double integer = 0;
double addition; bool done = false;
while (*text != '\0' && ((*text >= '0' && *text <= maxNumeric) || (maxAlpha != 0 && *text >= 'A' && *text <= maxAlpha))) // Parse integer part of number
do
{ {
addition = ((*text >= '0' && *text <= maxNumeric) ? (*text - '0') : (*text - 'A' + 10)) * 1.0; double addition;
integer = integer * base + addition; if (*text == '\0')
{
done = true;
continue;
}
if (*text >= '0' && *text <= maxNumeric)
{
addition = (*text - '0') * 1.0;
}
else if (maxAlphaUpper != 0 && *text >= 'A' && *text <= maxAlphaUpper)
{
addition = (*text - 'A' + 10) * 1.0;
}
else if (maxAlphaLower != 0 && *text >= 'a' && *text <= maxAlphaLower)
{
addition = (*text - 'a' + 10) * 1.0;
}
else
{
done = true;
continue;
}
integer = integer * baseDouble + addition;
text++; text++;
pos++; pos++;
} } while (!done);
// Digits not found // Digits not found
if (pos == 0) if (pos == 0)
{ {
*length = 0; *length = 0;
*end = const_cast<char*>(text); *end = const_cast<char *>(text);
return new RealNumber(); return new RealNumber();
} }
// Parse fraction part of number
double fraction = 0.0; double fraction = 0.0;
double divisor = 1.0; double divisor = 1.0;
if (*text == fractionPoint && fractionPoint != '\0') if (*text == fractionPoint && fractionPoint != '\0')
{ {
done = false;
double addition;
text++; text++;
pos++; pos++;
while (*text != '\0' && ((*text >= '0' && *text <= maxNumeric) || (maxAlpha != '\0' && *text >= 'A' && *text <= maxAlpha))) do
{ {
addition = ((*text >= '0' && *text <= maxNumeric) ? (*text - '0') : (*text - 'A' + 10)); if (*text == '\0')
fraction = fraction * base + addition; {
divisor *= base; done = true;
continue;
}
if (*text >= '0' && *text <= maxNumeric)
{
addition = (*text - '0') * 1.0;
}
else if (maxAlphaUpper != 0 && *text >= 'A' && *text <= maxAlphaUpper)
{
addition = (*text - 'A' + 10) * 1.0;
}
else if (maxAlphaLower != 0 && *text >= 'a' && *text <= maxAlphaLower)
{
addition = (*text - 'a' + 10) * 1.0;
}
else
{
done = true;
continue;
}
fraction = fraction * baseDouble + addition;
divisor *= baseDouble;
text++; text++;
pos++; pos++;
} } while (!done);
} }
// Parse exponent part of number
double exp = 0.0; double exp = 0.0;
if (*text == 'e' || *text == 'E') if (*text == 'e' || *text == 'E')
{ {
double addition;
text++; text++;
pos++; pos++;
@ -390,17 +449,40 @@ Number *PositionalNumeralSystem::Parse(const char *text, unsigned int *length, c
if (sign != 0.0) if (sign != 0.0)
{ {
done = false;
text++; text++;
pos++; pos++;
while (*text != '\0' && ((*text >= '0' && *text <= maxNumeric) || (maxAlpha != 0 && *text >= 'A' && *text <= maxAlpha))) do
{ {
addition = ((*text >= '0' && *text <= maxNumeric) ? (*text - '0') : (*text - 'A' + 10)) * 1.0; if (*text == '\0')
exp = exp * base + addition; {
done = true;
continue;
}
if (*text >= '0' && *text <= maxNumeric)
{
addition = (*text - '0') * 1.0;
}
else if (maxAlphaUpper != 0 && *text >= 'A' && *text <= maxAlphaUpper)
{
addition = (*text - 'A' + 10) * 1.0;
}
else if (maxAlphaLower != 0 && *text >= 'a' && *text <= maxAlphaLower)
{
addition = (*text - 'a' + 10) * 1.0;
}
else
{
done = true;
continue;
}
exp = exp * baseDouble + addition;
text++; text++;
pos++; pos++;
} } while (!done);
exp *= sign; exp *= sign;
} }
else else
@ -411,14 +493,14 @@ Number *PositionalNumeralSystem::Parse(const char *text, unsigned int *length, c
} }
*length = pos; *length = pos;
*end = const_cast<char*>(text); *end = const_cast<char *>(text);
double dnumber = (integer + (fraction / divisor)); double dnumber = (integer + (fraction / divisor));
if (exp != 0.0) if (exp != 0.0)
{ {
// pow seems a bit off // pow seems a bit off
dnumber *= pow(base, exp + 4e-15); dnumber *= pow(baseDouble, exp + 4e-15);
} }
return new RealNumber(dnumber); return new RealNumber(dnumber);

View File

@ -57,12 +57,18 @@ protected:
const char* GetSpecialCase(Number *number); const char* GetSpecialCase(Number *number);
void IntegerToBuffer(double value, unsigned int digits, int* outdigits) const; void IntegerToBuffer(double value, unsigned int digits, int* outdigits) const;
double base; double baseDouble;
unsigned int digits; unsigned int digits;
char fractionPoint; char fractionPoint;
private: private:
const char* GetText(double number) const; const char* GetText(double number) const;
bool IsDigit(char *digit);
unsigned int baseInteger;
char maxNumeric;
char maxAlphaLower;
char maxAlphaUpper;
}; };
#endif #endif