Added overloads for the StringBuilderHelper.Append() method to limit the number of decimal places being displayed; wrote unit tests for the new functionality

git-svn-id: file:///srv/devel/repo-conversion/nusu@190 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2010-02-15 19:19:26 +00:00
parent 03eb31403d
commit 35a4da16fc
2 changed files with 107 additions and 20 deletions

View File

@ -166,6 +166,26 @@ namespace Nuclex.Support {
Assert.AreEqual("1000000000.0", builder.ToString()); Assert.AreEqual("1000000000.0", builder.ToString());
} }
/// <summary>Tests whether the number of decimal places can be restricted</summary>
[Test]
public void TestAppendFloatLimitDecimalPlaces() {
StringBuilder builder = new StringBuilder();
StringBuilderHelper.Append(builder, 0.00390625f, 3);
Assert.AreEqual("0.003", builder.ToString());
}
/// <summary>
/// Verifies that a float with no decimal places is correctly appended
/// </summary>
[Test]
public void TestAppendFloatWithoutDecimalPlaces() {
StringBuilder builder = new StringBuilder();
StringBuilderHelper.Append(builder, 0.00390625f, 0);
Assert.AreEqual("0", builder.ToString()); // Note: no rounding!
}
/// <summary> /// <summary>
/// Verifies the behavior of the helper with unsupported floating point values /// Verifies the behavior of the helper with unsupported floating point values
/// </summary> /// </summary>
@ -226,6 +246,26 @@ namespace Nuclex.Support {
Assert.AreEqual("1000000000000000000.0", builder.ToString()); Assert.AreEqual("1000000000000000000.0", builder.ToString());
} }
/// <summary>Tests whether the number of decimal places can be restricted</summary>
[Test]
public void TestAppendDoubleLimitDecimalPlaces() {
StringBuilder builder = new StringBuilder();
StringBuilderHelper.Append(builder, 0.00390625, 3);
Assert.AreEqual("0.003", builder.ToString()); // Note: no rounding!
}
/// <summary>
/// Verifies that a double with no decimal places is correctly appended
/// </summary>
[Test]
public void TestAppendDoubleWithoutDecimalPlaces() {
StringBuilder builder = new StringBuilder();
StringBuilderHelper.Append(builder, 0.00390625, 0);
Assert.AreEqual("0", builder.ToString());
}
/// <summary> /// <summary>
/// Verifies the behavior of the helper with unsupported double precision /// Verifies the behavior of the helper with unsupported double precision
/// floating point values /// floating point values

View File

@ -103,6 +103,22 @@ namespace Nuclex.Support {
/// is returned and the traditional double.ToString() method can be used. /// is returned and the traditional double.ToString() method can be used.
/// </remarks> /// </remarks>
public static bool Append(StringBuilder builder, float value) { public static bool Append(StringBuilder builder, float value) {
return Append(builder, value, int.MaxValue);
}
/// <summary>
/// Appends a floating point value to a string builder without generating garbage
/// </summary>
/// <param name="builder">String builder the value will be appended to</param>
/// <param name="value">Value that will be appended to the string builder</param>
/// <param name="decimalPlaces">Maximum number of decimal places to display</param>
/// <returns>Whether the value was inside the algorithm's supported range</returns>
/// <remarks>
/// Uses an algorithm that covers the sane range of possible values but will
/// fail to render extreme values, NaNs and infinity. In these cases, false
/// is returned and the traditional double.ToString() method can be used.
/// </remarks>
public static bool Append(StringBuilder builder, float value, int decimalPlaces) {
const int ExponentBits = 0xFF; // Bit mask for the exponent bits const int ExponentBits = 0xFF; // Bit mask for the exponent bits
const int FractionalBitCount = 23; // Number of bits for fractional part const int FractionalBitCount = 23; // Number of bits for fractional part
const int ExponentBias = 127; // Bias subtraced from exponent const int ExponentBias = 127; // Bias subtraced from exponent
@ -148,17 +164,24 @@ namespace Nuclex.Support {
recursiveAppend(builder, integral); recursiveAppend(builder, integral);
} }
builder.Append('.'); if(decimalPlaces > 0) {
builder.Append('.');
// Build the fractional part // Build the fractional part
if(fractional == 0) { if(fractional == 0) {
builder.Append('0'); builder.Append('0');
} else { } else {
while(fractional != 0) { while(fractional != 0) {
fractional *= 10; fractional *= 10;
int digit = (fractional >> FractionalBitCountPlusOne); int digit = (fractional >> FractionalBitCountPlusOne);
builder.Append(numbers[digit]); builder.Append(numbers[digit]);
fractional &= FractionalBits; fractional &= FractionalBits;
--decimalPlaces;
if(decimalPlaces == 0) {
break;
}
}
} }
} }
@ -178,6 +201,23 @@ namespace Nuclex.Support {
/// is returned and the traditional double.ToString() method can be used. /// is returned and the traditional double.ToString() method can be used.
/// </remarks> /// </remarks>
public static bool Append(StringBuilder builder, double value) { public static bool Append(StringBuilder builder, double value) {
return Append(builder, value, int.MaxValue);
}
/// <summary>
/// Appends a double precision floating point value to a string builder
/// without generating garbage
/// </summary>
/// <param name="builder">String builder the value will be appended to</param>
/// <param name="value">Value that will be appended to the string builder</param>
/// <param name="decimalPlaces">Maximum number of decimal places to display</param>
/// <returns>Whether the value was inside the algorithm's supported range</returns>
/// <remarks>
/// Uses an algorithm that covers the sane range of possible values but will
/// fail to render extreme values, NaNs and infinity. In these cases, false
/// is returned and the traditional double.ToString() method can be used.
/// </remarks>
public static bool Append(StringBuilder builder, double value, int decimalPlaces) {
const long ExponentBits = 0x7FF; // Bit mask for the exponent bits const long ExponentBits = 0x7FF; // Bit mask for the exponent bits
const int FractionalBitCount = 52; // Number of bits for fractional part const int FractionalBitCount = 52; // Number of bits for fractional part
const int ExponentBias = 1023; // Bias subtraced from exponent const int ExponentBias = 1023; // Bias subtraced from exponent
@ -223,17 +263,24 @@ namespace Nuclex.Support {
recursiveAppend(builder, integral); recursiveAppend(builder, integral);
} }
builder.Append('.'); if(decimalPlaces > 0) {
builder.Append('.');
// Build the fractional part // Build the fractional part
if(fractional == 0) { if(fractional == 0) {
builder.Append('0'); builder.Append('0');
} else { } else {
while(fractional != 0) { while(fractional != 0) {
fractional *= 10; fractional *= 10;
long digit = (fractional >> FractionalBitCountPlusOne); long digit = (fractional >> FractionalBitCountPlusOne);
builder.Append(numbers[digit]); builder.Append(numbers[digit]);
fractional &= FractionalBits; fractional &= FractionalBits;
--decimalPlaces;
if(decimalPlaces == 0) {
break;
}
}
} }
} }