How to display 4 digits after a decimal pointer with exponential and power?
-
Hi All,
In my requirement the data is coming as QVariant and showing in the table as
6.41257e-13
-1.11515e-11
-0.13754e-3But my requirement is, only 4 digits with exp after decimal should display. For example
6.4125e-13
-1.1151e-11
-0.1375e-3I have implemented as
Qvariant MyWidget::set_decimalPoint(QVariant value){ double doubleValue = value.toDouble(); QString res = QString::number(doubleValue, 'e' , 4); return QVariant(res); }
But there is change in the output ie.. if input is
0.12345 it is converting it as 1.2345
0.11111 -> 1.1111e-1;
6.41257e-13 -> 6.4126e-13
-1.11515e-11 -> -1.1151e-11
-0.1234567889 -> -1.2346e-01
12.23456332 -> 1.2235e+01The above highlighted data is not proper output. I want to show only 4 digits after decimal point with out changing input data. X.XXXXeY
-
I doubt this is possible even with a simple printf() statement. You have to write this by yourself.
-
Hi @Bharath-kumar,
As @Christian-Ehrlicher said, the behaviour you want is not really built-in. Basically most (of not all) scientific / exponential notations prefer to shift the decimal point such that the there's only a single digit before the decimal point, and that digital should be non-zero. By doing this, the exponent at the end gives an accurate indication of the overall magnitude of the number.
That said, I thought I'd have some fun trying to solve for want you want... But first:
In my requirement the data is coming as QVariant and showing in the table as
6.41257e-13
-1.11515e-11
-0.13754e-3I have to assume that your
QVariant
values are actually strings, because otherwise, you would not have-0.13754e-3
for example. If they weredouble
values (within theQVariant
s), then what you have is a bunch of binary digits, and they would not be rendered like that visually. I'm assuming then, that yourQVariant::toDouble()
call is actually convertingQVariant(QString())
todouble
, which is certainly a valid conversion, according to the Qt docs.So, with that in mind, here's one (not necessarily great) solution:
QVariantList values { QStringLiteral("0.12345"), QStringLiteral("0.11111"), QStringLiteral("6.41257e-13"), QStringLiteral("-1.11515e-11"), QStringLiteral("-0.1234567889"), QStringLiteral("12.23456332"), }; for (const QVariant &value: values) { QString stringValue = value.toString(); const static QRegularExpression re(QStringLiteral("^([^.]*\\.)(\\d{5,})(.*)$")); QRegularExpressionMatch match = re.match(stringValue); if (match.hasMatch()) { const unsigned long fraction = (match.captured(2).first(5).toULong()+5L)/10L; stringValue = match.captured(1) + QString::number(fraction) + match.captured(3); } qDebug().noquote() << value.toString() << stringValue; }
The output is:
0.12345 0.1235 0.11111 0.1111 6.41257e-13 6.4126e-13 -1.11515e-11 -1.1152e-11 -0.1234567889 -0.1235 12.23456332 12.2346
So, how does it work? Well, first it uses a regex pattern to split numbers into:
- everything before (and including) the decimal point
- 5 or more digits after the decimal point
- anything after the digits in #2
So, for example,
-1.11515e-11
is split into:-1.
11515
e-11
Then middle fraction (eg
11515
) is shortened (rounded) to 4 digits (eg1152
). And finally the first and last parts a joined back with the new shortened fraction (eg-1.
append1152
appende-11
). In this way, whatever the current whole units and exponents are, remain intact, without being altered at all. Only the fractions is rounded to 4 digits.As for the shortening / rounding, that bit deserves slightly more explanation:
const unsigned long fraction = (match.captured(2).first(5).toULong()+5L)/10L;
We first truncate to just the leading five digits. Now I know you only wanted four digits, but here's the trick: if we extract 5 digits, and divide by 10 (ie the
/10L
at the end), then of course we end up with just 4 digits, as desired. But, by having that 5th digit, then adding 5, before we divide by 10, then we have effectively rounded the 4th digit (up or down) instead of simply truncating.Also note, if the pattern is not matched at all (eg if the number is invalid, or it already only has 4 or less decimals, etc), then the solution above uses the existing string value as-is. That may or may not be what you want.
Also note, this will not support locales outside of the one you're showing in your examples (eg some countries use different separators, etc).
Anyway, hope that gives you some inspiration. There's probably better solutions out there, but I had fun coming up with this one ;)
Cheers.
-
Yeah thanks for the solution. But I am trying in different way.
My Implementation is:Qvariant MyWidget::set_decimalPoint(QVariant data){ if(data.canConvert<QString>()) { QString dataString = data.toString(); if(dataString == "0") { return data; } int decimalPointIndex = dataString.index(.); int digitsAfterDecimal = dataString.length() - decimalPointIndex -1; if(digitsAfterDecimal > 4) { double doubleValue = data.toDouble(); QString formattedString = QString::number(doubleValue, 'e' , 4); return QVariant(formattedString); } else{ return data; } } else { return data; } }
My requirement if data is int should show int only, if data is 1.1, 2.23,-0.012, 0.234 should show same as it is.
but if digits after decimal then I want to show X.XXXXe+-Y.
Above code is not working for 2.24, 4.25 even 2 digits after decimal. Because QString conversion giving 15 digits after decimal point. Can anyone please help me. -
@Bharath-kumar said in How to display 4 digits after a decimal pointer with exponential and power?:
Because QString conversion giving 15 digits after decimal point.
Where/how? I see
QString::number(doubleValue, 'e' , 4);
, how does that produce 15 digits after decimal point? Put in aqDebug() << formattedString
and show what input produces 15 digits? -
What I was trying to say is, after converting QVariant data to QString , the QString data has more digits after decimal point.
QString dataString = data.toString(); qDebug() << "dataString: "<<dataString << " data.toDouble: " << data.toDouble();
output:
dataString: "-2.2400000000000002" data.toDouble: -2.24
dataString: "4.4500000000000002" data.toDouble: 4.45
dataString: "0.12345" data.toDouble: 0.12345
dataString: "-0.97999999999999998" data.toDouble: -0.98 -
@Bharath-kumar said in How to display 4 digits after a decimal pointer with exponential and power?:
the QString data has more digits after decimal point.
What do you expect? You don't specify the number of digits after the decimal point so a reasonable default value is used.
-
@Bharath-kumar
As @Christian-Ehrlicher has said. I don't understand: in your code you know how to produce a certain number of digits viaQString formattedString = QString::number(doubleValue, 'e' , 4);
, so why do you haveQString dataString = data.toString();
earlier and expect that to produce a limited number of digits?