C / C ++ rounds decimals with precision, efficiently

I am trying to optimize the following. Below is the code:

If a = 0.775 and I need an accuracy of 2 dp, then a => 0.78

In principle, if the last digit is 5, it rounds up to the next digit, otherwise it is not.

My problem was that 0.45 is not rounded to 0.5 with 1 decimal point, as the value is saved as 0.499999999343 .... and setprecision rounds it to 0.4.

This is why setprecision is forced to be higher setprecision(p+10), and then if it really ends at 5, add a small amount for proper rounding.

After execution, it compares a with string b and returns the result. The problem is that this function is called several billion times, which makes the craw program. Any best ideas on how to rewrite / optimize this and what features in the code are so heavy on the machine?

bool match(double a,string b,int p) { //p = precision no greater than 7dp

    double t[] = {0.2, 0.02, 0.002, 0.0002, 0.00002, 0.000002, 0.0000002, 0.00000002};

    stringstream buff;
    string temp;

    buff << setprecision(p+10) << setiosflags(ios_base::fixed) << a; // 10 decimal precision
    buff >> temp;

    if(temp[temp.size()-10] == '5')  a += t[p]; // help to round upwards

    ostringstream test;
    test << setprecision(p) << setiosflags(ios_base::fixed) << a;
    temp = test.str();

    if(b.compare(temp) == 0) return true;

    return false;
}
+3
source share
10 answers

I wrote an integer square root subroutine with no more than two dozen ASM lines, without any API calls - and it could still only make about 50 million SqRoots / second (this was about five years ago ...),

What I am doing is that if you are going for billions of calls, even today the technology will suffocate.

, , API-. , API , . , . , . .

, , - ++, , ASM, . , , .

, ASM . 10 ^ 7 ( 10 ^ p, , ), . .

, .

<--Microsoft Specific-->
, ++ ( , ) ASM, ++. ASM .
<--End Microsoft Specific-->

+2

, , . this.

+2

, 0.005 , 0.0005 .. snprintf - "% 1.2f" (, 1,3- ..) . .

+2

, t [] , .

+2
+1

:

#include <cmath>

double setprecision(double x, int prec) {
    return 
        ceil( x * pow(10,(double)prec) - .4999999999999)
        / pow(10,(double)prec);
}

, , . , , , .

, :

2.345* 100 (10 to the 2nd power) = 234.5
234.5 - .4999999999999 = 234.0000000000001
ceil( 234.0000000000001 ) = 235
235 / 100 (10 to the 2nd power) = 2.35

.4999999999999 - ++ double 32- . 64- , , , . 32- , , , i. . 234.00000000000001 234 (32-) .

+1

, . , , . , , , "" . , double , .

double string_to_double(const std::string &s)
{
    std::stringstream buffer(s);
    double d = 0.0;
    buffer >> d;
    return d;
}

bool match(const std::string &guess, double answer, int precision)
{
    const static double thresh[] = { 0.5, 0.05, 0.005, 0.0005, /* etc. */ };
    const double g = string_to_double(guess);
    const double delta = g - answer;
    return -thresh[precision] < delta && delta <= thresh[precision];
}

, ( ), .

bool match2(const std::string &guess, double answer, int precision)
{
    const static double thresh[] = {0.5, 0.05, 0.005, 0.0005, /* etc. */ };
    const double rounded = answer + thresh[precision];
    std::stringstream buffer;
    buffer << std::setprecision(precision) << rounded;
    return guess == buffer.str();
}

, , , , .

0

, , p. b.

, double - ( ) - , ( p == 1 = > abs (p-a) < 0,05)

0

, .

, . ( ). .., .

, 200- , , 200 float varaible , .

I beleive Boost "BigDecimal" , , , .

0

, . 0,45 0,45 , 0.44999999343 - .

, - 3 , , .

, ?

abs(a-b) < 10 ** -p

-1
source

Source: https://habr.com/ru/post/1712800/


All Articles