programing

플로트를 최소 증분(또는 그에 근접)으로 변경하는 방법은 무엇입니까?

prostudy 2022. 6. 22. 21:47
반응형

플로트를 최소 증분(또는 그에 근접)으로 변경하는 방법은 무엇입니까?

나는 가지고 있다double가치f가능한 한 원본에 가깝지만 원본보다 훨씬 큰(또는 더 작은) 새로운 값을 얻기 위해 매우 큰(또는 더 작은) 방법을 원합니다.

마지막 비트에 근접할 필요는 없습니다.어떤 변경을 하든 원래 값으로 반올림하지 않고 다른 값을 생성하는 것이 더 중요합니다.

math.h 파일을 확인합니다.운이 좋으면 및 함수가 정의되어 있습니다.C99 규격의 일부로서 포터블 및 플랫폼에 의존하지 않는 방법으로, 고객이 원하는 대로 동작합니다.

이를 위한 또 다른 방법(예비 솔루션일 수 있음)은 플로트를 가수 및 지수 부품으로 분해하는 것입니다.증분은 간단합니다. 1개만 더하면 됩니다.오버플로가 발생하면 지수를 증가시켜 이 문제를 해결해야 합니다.감소는 같은 방식으로 작동합니다.

편집: 코멘트에서 지적한 바와 같이, 바이너리 표현으로 플로트를 증가시키는 것만으로 충분합니다.가수 오버플로가 지수를 증가시킬 거고 그게 바로 우리가 원하는 거야

간단히 말해서 다음에 하는 것과 같은 것입니다.

하지만 이것은 완전히 휴대할 수 있는 것은 아닙니다.엔디안리스와 모든 기계에 IEEE 플로트가 탑재되어 있는 것은 아니라는 점에 대처해야 합니다(좋습니다.마지막 이유는 좀 더 학술적인 것입니다).

또한 NAN과 Infinite를 다루는 것도 조금 까다로울 수 있습니다.단순히 숫자가 아니라 정의상 그대로 늘릴 수는 없습니다.

절대적인 관점에서 부동소수점 값에 추가하여 새로운 고유값을 만들 수 있는 최소량은 값의 현재 크기에 따라 달라집니다. 이 값은 유형의 기계 엡실론에 현재 지수를 곱한 값입니다.

부동소수점 표현에 대해서는 IEEE 사양을 참조하십시오.가장 간단한 방법은 값을 정수 유형으로 재해석하고 1을 추가한 다음 기호와 지수 비트를 검사하여 기호를 뒤집거나 NaN을 생성하지 않았는지 확인하는 것입니다.

또는 frexp를 사용하여 현재 가수와 지수를 구하고 추가할 값을 계산할 수 있습니다.

u64 &x = *(u64*)(&f);
x++;

네, 정말이에요.

편집: 지적하신 바와 같이 -ve 수치, Inf, Nan 또는 오버플로에 대응하고 있지 않습니다.위의 보다 안전한 버전은

u64 &x = *(u64*)(&f);
if( ((x>>52) & 2047) != 2047 )    //if exponent is all 1's then f is a nan or inf.
{
    x += f>0 ? 1 : -1;
}

이것이 원하는 것은 아닐 수 있지만, 여전히 numeric_limits가 사용되고 있는 경우가 있습니다.특히 min()과 엡실론()의 멤버.

mydouble + numeric_limits:: epsilon()과 같은 것은 mydouble이 이미 엡실론에 가깝지 않은 한 당신이 원하는 것을 할 수 있다고 생각하지 않습니다.그렇다면 운이 좋으시군요.

조금 전에 이 코드를 발견했는데, 이 코드를 올릴 수 있는 최소값을 판별하는 데 도움이 될 수 있습니다.유감스럽게도 이 코드에 대한 참조가 기억나지 않습니다.

#include <stdio.h>

int main()
{
    /* two numbers to work with */
    double number1, number2;    // result of calculation
    double result;
    int counter;        // loop counter and accuracy check

    number1 = 1.0;
    number2 = 1.0;
    counter = 0;

    while (number1 + number2 != number1) {
        ++counter;
        number2 = number2 / 10;
    }
    printf("%2d digits accuracy in calculations\n", counter);

    number2 = 1.0;
    counter = 0;

    while (1) {
        result = number1 + number2;
        if (result == number1)
            break;
        ++counter;
        number2 = number2 / 10.0;
    }

    printf("%2d digits accuracy in storage\n", counter );

    return (0);
}

표준 ++ 증분이 기능을 정지하는 값은 9,007,199,254,740,992입니다.

나도 똑같은 일을 해야 했고 이 코드를 생각해 냈어.

double DoubleIncrement(double value)
{
  int exponent;
  double mantissa = frexp(value, &exponent);
  if(mantissa == 0)
    return DBL_MIN;

  mantissa += DBL_EPSILON/2.0f;
  value = ldexp(mantissa, exponent);
  return value;
}

언급URL : https://stackoverflow.com/questions/155378/how-to-alter-a-float-by-its-smallest-increment-or-close-to-it

반응형