가 나는 double
값 f
을 가지고 (이상 또는 이하) 여전히 원래하지만 최대한 가까운보다 확실히 더 클 수있는 새로운 가치를 아주 약간 큰 (또는 작은)를 조금씩 이동하는 방법을하고자하는 원래 .플로트를 조금씩 늘리거나 변경하는 방법?
이 가까이 아래에있을 필요가 없습니다 마지막 비트는 내가 다른 값을 생성하고 다시 원래로 반올림하지 않도록 보장 할 어떤 변화가 더 중요합니다.
가 나는 double
값 f
을 가지고 (이상 또는 이하) 여전히 원래하지만 최대한 가까운보다 확실히 더 클 수있는 새로운 가치를 아주 약간 큰 (또는 작은)를 조금씩 이동하는 방법을하고자하는 원래 .플로트를 조금씩 늘리거나 변경하는 방법?
이 가까이 아래에있을 필요가 없습니다 마지막 비트는 내가 다른 값을 생성하고 다시 원래로 반올림하지 않도록 보장 할 어떤 변화가 더 중요합니다.
math.h 파일을 확인하십시오. 운이 좋은 경우 nextafter
및 nextafterf
함수가 정의되어 있습니다. 그들은 당신이 휴대 가능하고 플랫폼에 독립적 인 방식으로 원하는 것을 정확하게 수행하며 C99 표준의 일부입니다.
(대체 솔루션이 될 수있다)을 할 수있는 또 다른 방법은 가수와 지수 부분으로 플로트를 분해하는 것입니다. 증분은 쉽습니다. 가수에 하나만 추가하면됩니다. 오버 플로우가 발생하면 지수를 증가시켜 처리해야합니다. 감소 작업은 같은 방식으로 작동합니다.
EDIT : 주석에서 지적한대로 이진수 표현에서 부동 소수점을 증가 시키면 충분합니다. 가수 - 오버플로는 지수를 증가시킬 것이며, 이는 우리가 원하는 것입니다.
간단히 말해서 nextafter가하는 것과 동일한 내용입니다.
그러나 완전히 이식되지는 않습니다. endianess와 모든 기계가 IEEE 플로트를 가지고있는 것은 아닙니다 (ok - 마지막 이유는 더 학문적입니다).
또한 NAN의 처리와 infinites이 까다로운 일이 될 수도있다. 단순히 숫자가 아닌 숫자로만 증분 할 수는 없습니다.오버 플로우가 원하는 지수로 넘어갈 것이므로 특별히 가수 오버플로를 처리하고 싶지는 않습니다. –
쿨 - 나는 결코 그것에 대해 생각하지 않았습니다. float를 정수로 증가 시키면 필요한 것을 정확하게 수행 할 수 있습니다. –
그것은 멋지다 :) 이제 누가 내 대답을 downvoted 바보가 그렇게 말하지 말아 줄래? –
u64 &x = *(u64*)(&f);
x++;
예.
편집 : 누군가 지적했듯이, 이것은 -ve numbers, Inf, Nan 또는 overflow를 제대로 처리하지 못합니다. 위의 안전한 버전은 절대적인 측면에서
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;
}
, 새로운 별개의 값이 값의 전류 크기에 따라 달라집니다하기 위해 부동 소수점 값에 추가 할 수있는 가장 작은 양이다; 형식의 machine epsilon에 현재 지수가 곱해질 것입니다. 포인트 represenation 부동의 IEEE spec 밖으로
확인합니다. 가장 간단한 방법은 값을 정수형으로 재 해석하고, 1을 더한 다음, 기호를 뒤집 지 않았거나 부호 및 지수 비트를 검사하여 NaN을 생성했는지 확인하십시오.
다른 방법으로는 현재 가수와 지수를 얻기 위해 frexp을 사용할 수 있으며, 따라서 추가 할 값을 계산합니다.
이 코드는 잠시 후에 발견되었습니다. 가장 작은 코드를 결정할 때 도움이 될 것입니다.내가 똑같은 일을 할 필요가이 코드를 함께했다
#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);
}
: 그것은 가치가 무엇인지에 대한
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;
}
좋은 점도 있습니다! –
, 값 불행하게도 나는이 코드에 대한 참조를 기억할 수 표준 ++ 증가 기능은 9,007199254740,992입니다.
이것은 정확히 원하는 것은 아니지만 여전히 numeric_limits 사용 중일 수 있습니다. 특히 min()과 엡실론() 멤버.
mydouble + numeric_limits :: 엡실론()이 mydouble이 이미 엡실론에 가깝지 않다면 원하는 것을 할 것이라고 생각하지 않습니다. 그렇다면 운이 좋다.
double 또는 float? 가지고있는 것에 따라 가장 작은 값이 달라집니다. – perimosocordiae
그래, 내 질문 제목과 설명이 일치하지 않았다는 것을 알았다. 나는 답이 두 가지 경우를 다룰 수 있다고 생각했다. – Owen