Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. Korean
  4. double 소수점 계산 관련 문의
Forum Updated to NodeBB v4.3 + New Features

double 소수점 계산 관련 문의

Scheduled Pinned Locked Moved Unsolved Korean
4 Posts 2 Posters 2.1k Views 1 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.
  • H Offline
    H Offline
    hlowd
    wrote on last edited by hlowd
    #1

    안녕하세요.

    qt 5.12.x 버전 사용중에 있고 소수점 계산 중에 궁금한 부분이 있어 문의드립니다.

    double a = 0.00025;
    double sum = 0.0;

    for(int i = 0; i < 100000; i++)
    {
    sum += a;
    }

    이렇게 계산을 할 경우 0.00025씩 증가하여야 하는데 값을 출력해보면 0.827998 이런식으로 깨져서 표시됩니다.

    아래와 같이 ceil이나 round 함수를 사용해도 0.00025씩 동일하게 증가하여 표시되게 하는 좋은 방법이 없을까요?

    ceil(a * 1000000) / 1000000;
    round(a * 1000000) / 1000000;

    ps) window 10, ubuntu 20.04 버전 동일합니다.

    Paul ColbyP 1 Reply Last reply
    0
    • H hlowd

      안녕하세요.

      qt 5.12.x 버전 사용중에 있고 소수점 계산 중에 궁금한 부분이 있어 문의드립니다.

      double a = 0.00025;
      double sum = 0.0;

      for(int i = 0; i < 100000; i++)
      {
      sum += a;
      }

      이렇게 계산을 할 경우 0.00025씩 증가하여야 하는데 값을 출력해보면 0.827998 이런식으로 깨져서 표시됩니다.

      아래와 같이 ceil이나 round 함수를 사용해도 0.00025씩 동일하게 증가하여 표시되게 하는 좋은 방법이 없을까요?

      ceil(a * 1000000) / 1000000;
      round(a * 1000000) / 1000000;

      ps) window 10, ubuntu 20.04 버전 동일합니다.

      Paul ColbyP Offline
      Paul ColbyP Offline
      Paul Colby
      wrote on last edited by
      #2

      Hi @hlowd, what you are seeing here an accumulative floating point error that comes from the fact that floating point numbers cannot represent every possible number exactly.

      The solution is to use a fixed-point approach instead of floating - ie using integers, but where the integers represent a decimal fraction instead of whole units.

      Easier explained with an example:

      This doesn't work, as you've shown already:

      #include <iostream>
      
      int main() {
        double a = 0.00025;
        double sum = 0.0;
        for(int i = 0; i < 100000; i++) {
          sum += a;
          std::cout << sum << std::endl;
        }
      }
      

      Outputs:

      0.00025
      0.0005
      0.00075
      0.001
      0.00125
      ...
      24.999
      24.9993
      24.9995
      24.9998
      25
      

      But this version:

      #include <iomanip>
      #include <iostream>
      
      int main() {   
        uint64_t a = 25; 
        uint64_t sum = 0;
        for(int i = 0; i < 100000; i++) {
          sum += a;
          std::cout << (sum/100000) << '.' << std::setfill('0') << std::setw(5) << (sum%10000) << std::endl;
        }
      }
      

      Outputs what you want (if I understand you correctly):

      0.00025
      0.00050
      0.00075
      0.00100
      0.00125
      ...
      24.09900
      24.09925
      24.09950
      24.09975
      25.00000
      

      Of course, the std::* stuff can be replaced with Qt-specific equivalents, but the problem is not specific to Qt (indeed, not specific to C++ either, but modern FPUs).

      Cheers.

      H 1 Reply Last reply
      0
      • Paul ColbyP Paul Colby

        Hi @hlowd, what you are seeing here an accumulative floating point error that comes from the fact that floating point numbers cannot represent every possible number exactly.

        The solution is to use a fixed-point approach instead of floating - ie using integers, but where the integers represent a decimal fraction instead of whole units.

        Easier explained with an example:

        This doesn't work, as you've shown already:

        #include <iostream>
        
        int main() {
          double a = 0.00025;
          double sum = 0.0;
          for(int i = 0; i < 100000; i++) {
            sum += a;
            std::cout << sum << std::endl;
          }
        }
        

        Outputs:

        0.00025
        0.0005
        0.00075
        0.001
        0.00125
        ...
        24.999
        24.9993
        24.9995
        24.9998
        25
        

        But this version:

        #include <iomanip>
        #include <iostream>
        
        int main() {   
          uint64_t a = 25; 
          uint64_t sum = 0;
          for(int i = 0; i < 100000; i++) {
            sum += a;
            std::cout << (sum/100000) << '.' << std::setfill('0') << std::setw(5) << (sum%10000) << std::endl;
          }
        }
        

        Outputs what you want (if I understand you correctly):

        0.00025
        0.00050
        0.00075
        0.00100
        0.00125
        ...
        24.09900
        24.09925
        24.09950
        24.09975
        25.00000
        

        Of course, the std::* stuff can be replaced with Qt-specific equivalents, but the problem is not specific to Qt (indeed, not specific to C++ either, but modern FPUs).

        Cheers.

        H Offline
        H Offline
        hlowd
        wrote on last edited by
        #3

        @Paul-Colby
        안녕하세요.

        우선 바쁘신 와중에 답변주셔서 감사합니다.

        답변해주신 부분에 대해 추가적으로 궁금한 내용이 있습니다.

        더해지는 값을 double 형 변수에 저장하는 것은 어려울까요?

        Paul ColbyP 1 Reply Last reply
        0
        • H hlowd

          @Paul-Colby
          안녕하세요.

          우선 바쁘신 와중에 답변주셔서 감사합니다.

          답변해주신 부분에 대해 추가적으로 궁금한 내용이 있습니다.

          더해지는 값을 double 형 변수에 저장하는 것은 어려울까요?

          Paul ColbyP Offline
          Paul ColbyP Offline
          Paul Colby
          wrote on last edited by
          #4

          @hlowd said in double 소수점 계산 관련 문의:

          더해지는 값을 double 형 변수에 저장하는 것은 어려울까요?

          Sure, you can convert the results to floating point numbers at any stage - eg inside the loop, or a the very end. For example:

          #include <iomanip>
          #include <iostream>
          
          int main() {   
            uint64_t a = 25; 
            uint64_t sum = 0;
            for(int i = 0; i < 100000; i++) {
              sum += a;
              const double sumAsFloat = sum/100000.0;
              std::cout << (sum/100000) << '.' << std::setfill('0') << std::setw(5) << (sum%100000)
                        << std::setprecision(10) << "  \t[" << sumAsFloat << ']' << std::endl;
            }
          }
          

          Outputs:

          0.00025         [0.00025]
          0.00050         [0.0005]
          0.00075         [0.00075]
          0.00100         [0.001]
          0.00125         [0.00125]
          24.99900        [24.999]
          24.99925        [24.99925]
          24.99950        [24.9995]
          24.99975        [24.99975]
          25.00000        [25]
          

          Cheers.

          PS: In printing both the uint64_t and double versions side-by-side, I realised there's was a small error in my previous reply, where the (sum%10000) should have had another 0, ie (sum%100000). I fixed that in the code in this reply :)

          1 Reply Last reply
          1

          • Login

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