문제

다음을 최적화하려고합니다. 코드 Bellow가 다음을 수행합니다.

a = 0.775이고 정밀 2 dp가 필요하다면 a => 0.78

기본적으로 마지막 숫자가 5 인 경우 다음 자리를 위로 둥글게합니다. 그렇지 않으면 그렇지 않습니다.

내 문제는 값이 0.4499999343으로 저장되므로 0.45가 0.5로 0.5로 둥글 지 않다는 것입니다.

그래서 SetPrecision이 더 높아야합니다 setprecision(p+10) 그런 다음 실제로 5로 끝나면 소량을 추가하여 올바르게 반올림하십시오.

완료되면 A를 문자열 B와 비교하고 결과를 반환합니다. 문제는이 기능을 수십억 번이라고하며 프로그램을 크로우는 것입니다. 이를 다시 작성 / 최적화하는 방법에 대한 더 나은 아이디어와 컴퓨터에서 코드의 기능이 어떤 기능이 너무 무겁습니까?

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;
}
도움이 되었습니까?

해결책

나는 API 호출이 전혀없는 수십 줄의 ASM 라인을 가진 정수 광장 뿌리 서브 루틴을 썼습니다. 여전히 약 5 천만 평방 피트/초만 할 수있었습니다 (약 5 년 전 ...).

내가 만드는 요점은 수십억 건의 전화를 가면 오늘날의 기술조차 질식 할 것입니다.

그러나 속도를 높이기 위해 실제로 노력하고 싶다면 인간적으로 가능한 많은 API 사용법을 제거하십시오. 이를 위해서는 라이브러리가 귀하를 위해 수행하는 대신 API 작업을 수동으로 수행해야 할 수도 있습니다. 구체적으로 모든 유형의 스트림 작동을 제거하십시오. 이것들은이 맥락에서 흙보다 느립니다. 당신은 정말로 거기에서 즉흥적으로해야 할 수도 있습니다.

그 후에 남은 유일한 일은 Custom ASM으로 가능한 많은 C ++ 라인을 대체하는 것입니다. 그러나 당신은 그것에 대한 완벽 주의자가되어야합니다. CPU 캐시 및 스택 공간의 모든 바이트뿐만 아니라 모든 CPU 사이클 및 등록을 최대한 활용해야합니다.

플로팅 포인트 대신 정수 값을 사용하는 것을 고려할 수 있습니다. 이는 훨씬 더 친숙하고 훨씬 효율적이기 때문입니다. 소수점을 오른쪽으로 끝까지 이동하려면 숫자에 10^7 (또는 논리를 형성하는 방법에 따라 10^P)을 곱해야합니다. 그런 다음 부동 소수점을 기본 정수로 안전하게 변환 할 수 있습니다.

나머지는 컴퓨터 하드웨어에 의존해야합니다.

<--Microsoft Specific-->
또한 C ++ 식별자 (Donnie DeBoer가 언급 한대로 정적 식별자 포함)는 C ++ 코드에 중첩 된 ASM 블록에서 직접 액세스 할 수 있다고 덧붙였습니다. 이것은 인라인 ASM을 산들 바람으로 만듭니다.
<--End Microsoft Specific-->

다른 팁

원하는 숫자에 따라 플로팅 포인트 대신 고정점 번호를 사용하고 싶을 수도 있습니다. 빠른 검색이 나타납니다 이것.

정밀도에 0.005를 수백 번, 수천에 대해 0.0005 등을 추가 할 수 있다고 생각합니다. Snprintf 결과는 "%1.2f"(백분의 1.3f, 1.3f 천 분의 1 등)와 같은 결과를 끈을 비교할 수 있다고 생각합니다. 이 논리를 테이블 에이드하거나 매개 변수화 할 수 있어야합니다.

이중 t [] 정적으로 만들어서 게시 된 코드에 일부 주요 사이클을 저장하여 계속해서 할당되지 않도록합니다.

대신 시도해보십시오.

#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

.499999999999는 32 비트 시스템에서 C ++ 더블의 정밀성 때문에 선택되었습니다. 64 비트 플랫폼에 있다면 더 많은 9 개가 필요할 것입니다. 32 비트 시스템에서 9 개를 더 늘리면 UP 대신 오버플로와 둥글게됩니다. 즉, 234.00000000000001은 32 비트 환경에서 더블에서 234로 잘립니다.

부동 소수점 (부정확 한 표현)을 사용한다는 것은 실제 숫자에 대한 정보를 잃어버린 것을 의미합니다. 퍼지 값을 추가하여 더블에 저장된 값을 단순히 "고정"할 수는 없습니다. 그것은 특정 사례를 고칠 수 있지만 (.45와 같은) 다른 경우를 끊을 것입니다. 반올림 된 숫자를 반올림하게 될 것입니다.

관련 기사는 다음과 같습니다.http://www.theeregister.co.uk/2006/08/12/floating_point_Approximation/

나는 당신이 실제로 무엇을 의미하는지 추측하고 있습니다. 문자열에 더블에 대한 소수점 표현이 포함되어 있는지 확인하려고합니다. 아마도 그것은 산술 퀴즈 프로그램이며 사용자의 응답이 실제 답변에 "충분히 가깝다"고 확인하려고합니다. 이 경우라면 문자열을 더블로 변환하고 두 더블 사이의 차이의 절대 값이 약간의 공차 내에 있는지 확인하는 것이 간단 할 수 있습니다.

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();
}

이 두 솔루션은 샘플 코드보다 빠르야하지만 실제로 원하는 작업을 수행하는지 확실하지 않습니다.

내가 보는 한 당신이 P 포인트에 둥근 A가 동일인지 확인하고 있습니다. b.

A를 문자열로 변경하고 다른 방법으로 만들고 문자열을 두 배로 변경하십시오 (작은 테이블을 사용하는 곱하기 및 추가 또는 추가 첨가물 만) - 두 숫자를 모두 설명하고 기판이 적절한 범위인지 확인하십시오 (p == 1 => abs. (PA) <0.05)

옛날 개발자들은 옛날 나라의 파운드, 실링 및 펜스의 암흑 시대부터 속임수를 쓰고 있습니다.

트릭은 값을 절반 펜으로 전체 숫자로 저장하는 것이 었습니다. (또는 가장 작은 단위가 무엇이든). 그러면 모든 후속 산술은 간단한 정수 산술과 반올림 등이 스스로 처리됩니다.

따라서 귀하는 귀하가 계산하는 모든 것의 200 분의 단위로 데이터를 저장하고,이 값에 대한 간단한 정수 계산을 수행하고, 결과를 표시하려면 200으로 200으로 분할하십시오.

나는 요즘 "Bigdecimal"라이브러리를 수행하지만, 런타임 속도에 대한 요구 사항은 아마도이 우수한 솔루션을 배제 할 것입니다.

당신이하려는 것은 실제 반올림이 아닌 것 같습니다. 0.45는 실제로 이진 표기법에서 0.45이며 0.44999999343은 동일하지 않습니다.

먼저 3 진수로, 두 개, 2 개, 1 개로 말하면 여러 반올림을해야 할 수도 있습니다.

문제는 무엇을 성취하려고합니까? 일치 기준이어야합니다

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

대신에?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top