Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. How to display 4 digits after a decimal pointer with exponential and power?
Forum Updated to NodeBB v4.3 + New Features

How to display 4 digits after a decimal pointer with exponential and power?

Scheduled Pinned Locked Moved Unsolved C++ Gurus
8 Posts 4 Posters 814 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Bharath kumar
    wrote on 17 May 2024, 06:34 last edited by
    #1

    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-3

    But my requirement is, only 4 digits with exp after decimal should display. For example
    6.4125e-13
    -1.1151e-11
    -0.1375e-3

    I 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+01

    The above highlighted data is not proper output. I want to show only 4 digits after decimal point with out changing input data. X.XXXXeY

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 17 May 2024, 06:54 last edited by
      #2

      I doubt this is possible even with a simple printf() statement. You have to write this by yourself.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      1
      • P Offline
        P Offline
        Paul Colby
        wrote on 17 May 2024, 13:34 last edited by Paul Colby
        #3

        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-3

        I have to assume that your QVariant values are actually strings, because otherwise, you would not have -0.13754e-3 for example. If they were double values (within the QVariants), then what you have is a bunch of binary digits, and they would not be rendered like that visually. I'm assuming then, that your QVariant::toDouble() call is actually converting QVariant(QString()) to double, 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:

        1. everything before (and including) the decimal point
        2. 5 or more digits after the decimal point
        3. anything after the digits in #2

        So, for example, -1.11515e-11 is split into:

        1. -1.
        2. 11515
        3. e-11

        Then middle fraction (eg 11515) is shortened (rounded) to 4 digits (eg 1152). And finally the first and last parts a joined back with the new shortened fraction (eg -1. append 1152 append e-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.

        1 Reply Last reply
        2
        • B Offline
          B Offline
          Bharath kumar
          wrote on 24 May 2024, 08:23 last edited by Bharath kumar
          #4

          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.

          J 1 Reply Last reply 24 May 2024, 08:37
          0
          • B Bharath kumar
            24 May 2024, 08:23

            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.

            J Offline
            J Offline
            JonB
            wrote on 24 May 2024, 08:37 last edited by
            #5

            @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 a qDebug() << formattedString and show what input produces 15 digits?

            1 Reply Last reply
            0
            • B Offline
              B Offline
              Bharath kumar
              wrote on 24 May 2024, 08:52 last edited by
              #6

              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

              C J 2 Replies Last reply 24 May 2024, 09:05
              0
              • B Bharath kumar
                24 May 2024, 08:52

                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

                C Offline
                C Offline
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote on 24 May 2024, 09:05 last edited by
                #7

                @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.

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                1 Reply Last reply
                1
                • B Bharath kumar
                  24 May 2024, 08:52

                  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

                  J Offline
                  J Offline
                  JonB
                  wrote on 24 May 2024, 09:08 last edited by
                  #8

                  @Bharath-kumar
                  As @Christian-Ehrlicher has said. I don't understand: in your code you know how to produce a certain number of digits via QString formattedString = QString::number(doubleValue, 'e' , 4);, so why do you have QString dataString = data.toString(); earlier and expect that to produce a limited number of digits?

                  1 Reply Last reply
                  0

                  5/8

                  24 May 2024, 08:37

                  • Login

                  • Login or register to search.
                  5 out of 8
                  • First post
                    5/8
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved