Format fixed-point numbers
This commit is contained in:
parent
531cae51a3
commit
f2eb99bab0
@ -1233,7 +1233,7 @@ private uint128 raise2ToExp(double value) @nogc nothrow pure @safe
|
|||||||
|
|
||||||
private int indexMismatch(ulong low, ulong high) @nogc nothrow pure @safe
|
private int indexMismatch(ulong low, ulong high) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
enum ulong power10 = 10000000000U;
|
enum ulong power10 = 10000000000UL;
|
||||||
const ulong a = low / power10;
|
const ulong a = low / power10;
|
||||||
const ulong b = high / power10;
|
const ulong b = high / power10;
|
||||||
int index;
|
int index;
|
||||||
@ -1346,6 +1346,83 @@ do
|
|||||||
assert(e == 26);
|
assert(e == 26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private char[] errolFixed(double value,
|
||||||
|
return ref char[512] buffer,
|
||||||
|
out int exponent) @nogc nothrow pure @safe
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(value >= 16.0 && value <= 9.007199254740992e15);
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
auto decimal = cast(ulong) value;
|
||||||
|
auto n = cast(double) decimal;
|
||||||
|
|
||||||
|
double midpoint = value - n;
|
||||||
|
double leftBoundary = (previous(value) - n + midpoint) / 2.0;
|
||||||
|
double rightBoundary = (next(value) - n + midpoint) / 2.0;
|
||||||
|
|
||||||
|
char[21] intBuffer;
|
||||||
|
auto intSlice = integral2String(decimal, intBuffer);
|
||||||
|
copy(intSlice, buffer);
|
||||||
|
exponent = cast(int) intSlice.length;
|
||||||
|
|
||||||
|
size_t position = exponent;
|
||||||
|
if (midpoint != 0.0)
|
||||||
|
{
|
||||||
|
while (midpoint != 0.0)
|
||||||
|
{
|
||||||
|
leftBoundary *= 10.0;
|
||||||
|
const leftDigit = cast(ubyte) leftBoundary;
|
||||||
|
leftBoundary -= leftDigit;
|
||||||
|
|
||||||
|
midpoint *= 10.0;
|
||||||
|
const middleDigit = cast(ubyte) midpoint;
|
||||||
|
midpoint -= middleDigit;
|
||||||
|
|
||||||
|
rightBoundary *= 10.0;
|
||||||
|
const rightDigit = cast(ubyte) rightBoundary;
|
||||||
|
rightBoundary -= rightDigit;
|
||||||
|
|
||||||
|
buffer[position++] = cast(char) (middleDigit + '0');
|
||||||
|
|
||||||
|
if (rightDigit != leftDigit || position > 50)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (midpoint > 0.5
|
||||||
|
|| ((midpoint == 0.5) && (buffer[position - 1] & 0x1)))
|
||||||
|
{
|
||||||
|
++buffer[position - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (; buffer[position - 1] == '0'; --position)
|
||||||
|
{
|
||||||
|
buffer[position - 1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer[0 .. position];
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
char[512] num;
|
||||||
|
int exponent;
|
||||||
|
{
|
||||||
|
assert(errolFixed(16.0, num, exponent) == "16");
|
||||||
|
assert(exponent == 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assert(errolFixed(38234.1234, num, exponent) == "382341234");
|
||||||
|
assert(exponent == 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a float value, returns the significant bits, and the position of the
|
* Given a float value, returns the significant bits, and the position of the
|
||||||
* decimal point in $(D_PARAM exponent). +/-Inf and NaN are specified by
|
* decimal point in $(D_PARAM exponent). +/-Inf and NaN are specified by
|
||||||
@ -1371,22 +1448,23 @@ private const(char)[] real2String(double value,
|
|||||||
exponent = special;
|
exponent = special;
|
||||||
return (bits.integral & ((1UL << 52) - 1)) != 0 ? "NaN" : "Inf";
|
return (bits.integral & ((1UL << 52) - 1)) != 0 ? "NaN" : "Inf";
|
||||||
}
|
}
|
||||||
|
else if (exponent == 0 && (bits.integral << 1) == 0) // Is zero?
|
||||||
if (exponent == 0 && (bits.integral << 1) == 0) // Is zero?
|
|
||||||
{
|
{
|
||||||
exponent = 1;
|
exponent = 1;
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
return buffer[0 .. 1];
|
return buffer[0 .. 1];
|
||||||
}
|
}
|
||||||
|
else if (value == double.max)
|
||||||
if (value == double.max)
|
|
||||||
{
|
{
|
||||||
copy("17976931348623157", buffer);
|
copy("17976931348623157", buffer);
|
||||||
exponent = 309;
|
exponent = 309;
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
else if (value >= 16.0 && value <= 9.007199254740992e15)
|
||||||
if (value > 9.007199254740992e15 && value < 3.40282366920938e38)
|
{
|
||||||
|
return errolFixed(value, buffer, exponent);
|
||||||
|
}
|
||||||
|
else if (value > 9.007199254740992e15 && value < 3.40282366920938e38)
|
||||||
{
|
{
|
||||||
return errol2(value, buffer, exponent);
|
return errol2(value, buffer, exponent);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user