Open fietser28 opened 1 year ago
I currently have the code below. It implements bullets 1,2 (it always shows prefix now) ,3 (excl. trailing zero's) and 4. It depends on sprintf and math functions like log10, pow, min, max.
static const char* SIScalePrefixes[] = { "p", "n","\u03bc", "m", " ", "k", "M", "G", "T" };
static const int SIScalePrefixExponents[] = {-12, -9, -6, -3, 0, 3 , 6, 9, 12 };
static const int SIScalePrefixExponentsBase = 4; // Index of 0 exponent
static const int SIScaleprefixExpLast = sizeof(SIScalePrefixExponents)/sizeof(SIScalePrefixExponents[0]) - 1;
void value2str(char* str, float value, int accuracy_exp, int total_digits, int after_point,
bool show_prefix, const char* unit)
{
// 0 is special case
if (value == 0.0f)
{
sprintf(str, " 0 %s", unit);
return;
}
// Determine sign
char sign = value < 0.0f ? '-' : ' ';
// Find exponent
int exponentRaw = floor(log10(abs(value)));
int exponent = std::max(exponentRaw, SIScalePrefixExponents[0]); // Lower limit of exponent
exponent = std::min(exponent, SIScalePrefixExponents[SIScaleprefixExpLast]); // Upper limit of exponent
exponent = std::max(exponent, accuracy_exp); // Don't go below accuracy
// Find prefix, exponent and mantissa to nearest enginering scale.
int exponentIndex = floor((float)exponent * 3.0f)/9 + SIScalePrefixExponentsBase;
exponentIndex = std::max(exponentIndex, (int)ceil(accuracy_exp / 3) + SIScalePrefixExponentsBase);
const char* prefix = SIScalePrefixes[exponentIndex];
float mantissa = abs(value) / pow(10, SIScalePrefixExponents[exponentIndex]); // raw mantissa
// Determine the number of digits after .
int fraction_digits = std::min(after_point, total_digits - (exponentRaw - exponent +1 ));
fraction_digits = std::min(fraction_digits, SIScalePrefixExponents[exponentIndex] - accuracy_exp);
// Format the string.
sprintf(str, "%c%.*f%s%s", sign, fraction_digits, mantissa, SIScalePrefixes[exponentIndex], unit);
} // value2str
A very common use case is to display and/or set measurement values (e.g. voltage, current, power, temperature,...) These have a specific way of displaying. I'm thinking of the following properties:
Nice to have: support styles for the different parts of the widget (digits before decimal point, digits behind decimal point, scale part of unit, unit, cursor)