Fixed doubleToStr function.

This commit is contained in:
Kapendev 2024-08-04 11:42:42 +03:00
parent fa058d8a7d
commit b37b6c3eb0
2 changed files with 76 additions and 45 deletions

View file

@ -17,8 +17,8 @@ Cleaning things in core.
* [ ] unions * [ ] unions
Was working on ascii. Was working on ascii.
Was about to rewrite the tests. Was rewriting the tests.
Might fix the doubleToStr function too. Was going to write the toValue tests and then I am done!
## IDEAS ## IDEAS

View file

@ -268,7 +268,6 @@ IStr pathDir(IStr path) {
} }
} }
// TODO: Make it more safe? Look at how Python does it.
IStr pathConcat(IStr[] args...) { IStr pathConcat(IStr[] args...) {
static char[1024][4] buffers = void; static char[1024][4] buffers = void;
static byte bufferIndex = 0; static byte bufferIndex = 0;
@ -367,59 +366,56 @@ IStr signedToStr(long value) {
return result; return result;
} }
// TODO: Fix N.00 bug and make it more simple. IStr doubleToStr(double value, ulong precision = 2) {
IStr doubleToStr(double value, uint precision = 2) {
static char[64] buffer = void; static char[64] buffer = void;
if (value != value) { if (precision == 0) {
return "nan"; return signedToStr(cast(long) value);
} }
auto result = buffer[]; // You know what this is. auto result = buffer[];
auto cleanNumber = value; // Number that has all the digits on the left side. auto cleanNumber = value;
auto fractionalDigitCount = 0; // Digit count on the right size. auto rightDigitCount = 0;
while (cleanNumber != cast(double) (cast(long) cleanNumber)) { while (cleanNumber != cast(double) (cast(long) cleanNumber)) {
fractionalDigitCount += 1; rightDigitCount += 1;
cleanNumber *= 10; cleanNumber *= 10;
} }
auto i = result.length; // We put the numbers in the buffer from right to left. // Add extra zeros at the end if needed.
auto cleanNumberStr = signedToStr(cast(long) cleanNumber); // I do this because it makes it easier to remove the zeros later.
// TODO: Fix N.00 bug and make it more simple. if (precision > rightDigitCount) {
if (cleanNumberStr.length <= fractionalDigitCount) { foreach (j; 0 .. precision - rightDigitCount) {
i -= cleanNumberStr.length; rightDigitCount += 1;
result.copyChars(cleanNumberStr, i); cleanNumber *= 10;
if (cleanNumberStr.length < fractionalDigitCount) {
i -= fractionalDigitCount - cleanNumberStr.length;
result[i .. i + fractionalDigitCount - cleanNumberStr.length] = '0';
}
i -= 2;
result[i] = '0';
result[i + 1] = '.';
} else {
if (fractionalDigitCount == 0) {
i -= (precision == 0 ? 1 : precision);
result[i .. i + (precision == 0 ? 1 : precision)] = '0';
i -= 1;
result[i] = '.';
i -= cleanNumberStr.length;
result.copyChars(cleanNumberStr, i);
} else {
i -= fractionalDigitCount;
result.copyChars(cleanNumberStr[$ - fractionalDigitCount .. $], i);
i -= 1;
result[i] = '.';
i -= (cleanNumberStr.length - fractionalDigitCount);
result.copyChars(cleanNumberStr[0 .. $ - fractionalDigitCount], i);
} }
} }
if (precision == 0) { // Digits go in the buffer from right to left.
result = result[i .. $]; auto cleanNumberStr = signedToStr(cast(long) cleanNumber);
} else { auto i = result.length;
result = result[i .. $ - fractionalDigitCount + (precision > fractionalDigitCount ? fractionalDigitCount : precision)]; // Check two cases: 0.NN, N.NN
if (cast(long) value == 0) {
i -= cleanNumberStr.length;
result.copyChars(cleanNumberStr, i);
foreach (j; 0 .. rightDigitCount - cleanNumberStr.length) {
i -= 1;
result[i] = '0';
} }
return result; i -= 2;
result.copyChars("0.", i);
} else {
i -= rightDigitCount;
result.copyChars(cleanNumberStr[$ - rightDigitCount .. $], i);
i -= 1;
result[i] = '.';
i -= cleanNumberStr.length - rightDigitCount;
result.copyChars(cleanNumberStr[0 .. $ - rightDigitCount], i);
}
// Remove extra zeros at the end if needed.
if (precision < rightDigitCount) {
result = result[0 .. $ - rightDigitCount + precision];
}
return result[i .. $];
} }
@trusted @trusted
@ -811,9 +807,44 @@ unittest {
assert(skipValue(str, ',') == ""); assert(skipValue(str, ',') == "");
assert(str.length == 0); assert(str.length == 0);
assert(boolToStr(false) == "false");
assert(boolToStr(true) == "true");
assert(charToStr('L') == "L");
assert(unsignedToStr(0) == "0");
assert(unsignedToStr(69) == "69");
assert(signedToStr(0) == "0");
assert(signedToStr(69) == "69");
assert(signedToStr(-69) == "-69");
assert(signedToStr(-69) == "-69");
assert(doubleToStr(0.00, 0) == "0");
assert(doubleToStr(0.00, 1) == "0.0");
assert(doubleToStr(0.00, 2) == "0.00");
assert(doubleToStr(0.00, 3) == "0.000");
assert(doubleToStr(0.60, 1) == "0.6");
assert(doubleToStr(0.60, 2) == "0.60");
assert(doubleToStr(0.60, 3) == "0.600");
assert(doubleToStr(0.09, 1) == "0.0");
assert(doubleToStr(0.09, 2) == "0.09");
assert(doubleToStr(0.09, 3) == "0.090");
assert(doubleToStr(69.0, 1) == "69.0");
assert(doubleToStr(69.0, 2) == "69.00");
assert(doubleToStr(69.0, 3) == "69.000");
assert(cStrToStr("Hello\0") == "Hello");
enum TestEnum {
one,
two,
}
assert(enumToStr(TestEnum.one) == "one");
assert(enumToStr(TestEnum.two) == "two");
// TODO: I need to write more tests for toValue procedures.
// TODO: ToValue tests write need!!!
auto text1 = "1.0"; auto text1 = "1.0";
auto conv1 = toDouble(text1); auto conv1 = toDouble(text1);
assert(conv1.value == 1.0); assert(conv1.value == 1.0);