Comments (2)
I don't know if this is your final fix but unfortunately, it does not work when a precision is specified in the above case.
Also, it does not work the same as before for all numbers when no precision is specified (default precision = 6 digits).
I didn't realize there were tests in bx so I tried adding more of them in the "vsnprintf f" test case.
#if 0 // Original code
REQUIRE(test("0.00390625", "%f", 0.00390625));
#else
REQUIRE(test("0.003906", "%f", 0.00390625) ); // No precision is specified so 6 digits are expected after the dot.
#endif
REQUIRE(test("-1.234567e-9", "%f", -1.234567e-9) );
// Test exponent with precision specifier.
REQUIRE(test("-1e-9", "%.0f", -1.234567e-9) );
REQUIRE(test("-1.2e-9", "%.1f", -1.234567e-9) );
REQUIRE(test("-1.23e-9", "%.2f", -1.234567e-9) );
REQUIRE(test("-1.234e-9", "%.3f", -1.234567e-9) );
REQUIRE(test("-1.2345e-9", "%.4f", -1.234567e-9) );
REQUIRE(test("-1.23456e-9", "%.5f", -1.234567e-9) );
REQUIRE(test("-1.234567e-9", "%.6f", -1.234567e-9) );
REQUIRE(test("-1.2345670e-9", "%.7f", -1.234567e-9) ); // Extra 0s with exponent
REQUIRE(test("-1.23456700e-9", "%.8f", -1.234567e-9) );
REQUIRE(test("-1.234567000e-9", "%.9f", -1.234567e-9) );
REQUIRE(test("-1.2345670000e-9", "%.10f", -1.234567e-9) );
// Test transcendental number
REQUIRE(test("3.141592", "%f", 3.1415926535897932) );
REQUIRE(test("3", "%.0f", 3.1415926535897932) );
REQUIRE(test("3.1", "%.1f", 3.1415926535897932) );
REQUIRE(test("3.14", "%.2f", 3.1415926535897932) );
REQUIRE(test("3.141", "%.3f", 3.1415926535897932) );
REQUIRE(test("3.1415", "%.4f", 3.1415926535897932) );
REQUIRE(test("3.14159", "%.5f", 3.1415926535897932) );
REQUIRE(test("3.141592", "%.6f", 3.1415926535897932) );
REQUIRE(test("3.1415926", "%.7f", 3.1415926535897932) );
REQUIRE(test("3.14159265", "%.8f", 3.1415926535897932) );
REQUIRE(test("3.141592653", "%.9f", 3.1415926535897932) );
REQUIRE(test("3.1415926535", "%.10f", 3.1415926535897932) );
REQUIRE(test("3.14159265358", "%.11f", 3.1415926535897932) );
REQUIRE(test("3.141592653589", "%.12f", 3.1415926535897932) );
REQUIRE(test("3.1415926535897", "%.13f", 3.1415926535897932) );
REQUIRE(test("3.14159265358979", "%.14f", 3.1415926535897932) );
REQUIRE(test("3.141592653589793", "%.15f", 3.1415926535897932) );
REQUIRE(test("3.1415926535897930", "%.16f", 3.1415926535897932) ); // The last digit is replaced by 0 because toString() has a 15-digit precision (?)
// Both of the above tests combined (transcendental number with large negative exponent)
REQUIRE(test("-3.141592e-9", "%f", -3.1415926535897932e-9) );
REQUIRE(test("-3e-9", "%.0f", -3.1415926535897932e-9) );
REQUIRE(test("-3.1e-9", "%.1f", -3.1415926535897932e-9) );
REQUIRE(test("-3.14e-9", "%.2f", -3.1415926535897932e-9) );
REQUIRE(test("-3.141e-9", "%.3f", -3.1415926535897932e-9) );
REQUIRE(test("-3.1415e-9", "%.4f", -3.1415926535897932e-9) );
REQUIRE(test("-3.14159e-9", "%.5f", -3.1415926535897932e-9) );
REQUIRE(test("-3.141592e-9", "%.6f", -3.1415926535897932e-9) );
REQUIRE(test("-3.1415926e-9", "%.7f", -3.1415926535897932e-9) );
REQUIRE(test("-3.14159265e-9", "%.8f", -3.1415926535897932e-9) );
REQUIRE(test("-3.141592653e-9", "%.9f", -3.1415926535897932e-9) );
REQUIRE(test("-3.1415926535e-9", "%.10f", -3.1415926535897932e-9) );
REQUIRE(test("-3.14159265358e-9", "%.11f", -3.1415926535897932e-9) );
REQUIRE(test("-3.141592653589e-9", "%.12f", -3.1415926535897932e-9) );
REQUIRE(test("-3.1415926535897e-9", "%.13f", -3.1415926535897932e-9) );
REQUIRE(test("-3.14159265358979e-9", "%.14f", -3.1415926535897932e-9) );
REQUIRE(test("-3.141592653589793e-9", "%.15f", -3.1415926535897932e-9) );
REQUIRE(test("-3.1415926535897930e-9", "%.16f", -3.1415926535897932e-9) ); // The last digit is replaced by 0 because toString() has a 15-digit precision (?)
And below is my version (including your code in #if 0/#endif
block):
static int32_t write(WriterI* _writer, double _d, const Param& _param, Error* _err)
{
char str[1024];
int32_t len = toString(str, sizeof(str), _d);
if (len == 0)
{
return 0;
}
if (_param.upper)
{
toUpperUnsafe(str, len);
}
const char* dot = strFind(str, INT32_MAX, '.');
if (NULL != dot)
{
#if 0 // Original code
const int32_t prec = INT32_MAX == _param.prec ? len - (dot + 1 - str) : _param.prec;
const int32_t precLen = int32_t(
dot
+ min(prec + _param.spec, 1)
+ prec
- str
);
if (precLen > len)
{
for (int32_t ii = len; ii < precLen; ++ii)
{
str[ii] = '0';
}
str[precLen] = '\0';
}
len = precLen;
#else
const int32_t prec = INT32_MAX == _param.prec ? 6 : _param.prec;
const char* strEnd = str + len;
const char* exponent = strFind(str, INT32_MAX, 'e');
const char* fracEnd = NULL != exponent ? exponent : strEnd;
char* fracBegin = &str[dot - str + min(prec + _param.spec, 1)];
const int32_t curPrec = int32_t(fracEnd - fracBegin);
// Move exponent to its final location after trimming or adding extra 0s.
if (fracEnd != strEnd)
{
const int32_t exponentLen = int32_t(strEnd - fracEnd);
char* finalExponentPtr = &fracBegin[prec];
memMove(finalExponentPtr, fracEnd, exponentLen); // NOTE: Use memMove because there may be overlap.
finalExponentPtr[exponentLen] = '\0';
len = int32_t(&finalExponentPtr[exponentLen] - str);
}
else
{
len = (int32_t)(fracBegin + prec - str);
}
if (curPrec < prec)
{
for (int32_t ii = curPrec; ii < prec; ++ii)
{
fracBegin[ii] = '0';
}
}
#endif
} else {
// TODO: If '#' is present (_param.spec == true) add dot?
}
return write(_writer, str, len, _param, _err);
}
It works for all the above cases. As a bonus, it also works for all tests in vsnprintf modifiers
case (the test failed with your fix).
I don't want to mess with the library's code style so please cleanup the code as you see fit.
EDIT: Changed "width" to "precision" in all cases. This issue is about the precision specifier :)
from bx.
Send PR. :)
from bx.
Related Issues (20)
- Is BX_MAKEFOURCC backwards? HOT 2
- 2 test failed on 64 bit Linux HOT 1
- makefile osx arguments error HOT 1
- MAME embedded bx missing crt0.h, suspect MacOSX configuration problem HOT 1
- Odd error in debug.cpp when trying to compile HOT 3
- Filepath getExt() returns incorrect extensions. HOT 3
- vsnprintf does not always nullterminate HOT 4
- simd128_ref.inl simd_shuf_AxBy case fail HOT 3
- atan2 gives the same value for (0, 1) and (0, -1)
- [typetraits.inl] msvc __is_aggregate error HOT 6
- m_count should use volatile ? HOT 1
- Compiling failing on GhostBSD HOT 1
- pthread_np.h does not exist on NetBSD HOT 1
- bx::normalize return bad result when simd is enable on macOS(M1)/iOS platform HOT 2
- bx::sqrt(0.f) will return NaN HOT 10
- Near-Zero values breaking the mtxLookAt function
- I'm confused about BX_NO_VTABLE, bx::AllocatorI, and UBSan reports. HOT 1
- Q: SIMD functions HOT 1
- Building on musl HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bx.