다음은 프로그램을 포함하여 double
이 IEEE 754 64 비트 2 진 부동 소수점으로 표시된다고 가정합니다. 그럴 가능성이 가장 높지만 C++ 표준에 의해 보장되지는 않습니다.
끝에서 시작 부분을 빼고 범위가 열렸는지 닫히는지를 조정하여 일정 시간 범위 내의 부호없는 정수를 계산할 수 있기 때문에 일정 시간 범위에서 두 배를 계산할 수 있습니다.
유한 비 음수 범위의 복식은 연속적인 정수 시퀀스를 형성하는 비트 패턴을 갖습니다. 예를 들어 범위 [1.0,2.0]에는 [0x3ff0_0000_0000_0000, 0x4000_0000_0000_0000] 범위의 각 정수에 대해 하나의 double이 포함됩니다.
double 형의 유한 양수 범위는 double 형이 부정적이됨에 따라 부호없는 비트 패턴의 값이 증가한다는 점을 제외하면 같은 방식으로 동작합니다.
범위에 양수와 음수가 모두 포함되어 있으면 음수가 아닌 범위와 다른 양수가 아닌 범위를 처리 할 수 있도록 범위를 0으로 분할하십시오.
대부분의 합병증은 정확한 계산을 원할 때 발생합니다. 이 경우 범위가 열렸는지 닫히는지를 조정하고 정확히 한 번만 0을 계산해야합니다.
귀하의 목적에 따라, 수십 억 개 중 하나 또는 두 개를 벗어나도 별 문제가되지 않을 수 있습니다.
다음은 아이디어를 보여주는 간단한 프로그램입니다. 오류 검사를 거의받지 못했으므로 본인 책임하에 사용하십시오.
#include <iostream>
#include <cmath>
using namespace std;
uint64_t count(double start, double end);
void testit(uint64_t expected, double start, double end) {
cout << hex << "Should be " << expected << ": " << count(start, end)
<< endl;
}
double increment(double data, int count) {
int i;
for (i = 0; i < count; i++) {
data = nextafter(data, INFINITY);
}
return data;
}
double decrement(double data, int count) {
int i;
for (i = 0; i < count; i++) {
data = nextafter(data, -INFINITY);
}
return data;
}
int main() {
testit((uint64_t) 1 << 52, 1.0, 2.0);
testit(5, 3.0, increment(3.0, 5));
testit(2, decrement(0, 1), increment(0, 1));
testit((uint64_t) 1 << 52, -2.0, -1.0);
testit(1, -0.0, increment(0, 1));
testit(10, decrement(0,10), -0.0);
return 0;
}
// Return the bit pattern representing a double as
// a 64-bit unsigned integer.
uint64_t toInteger(double data) {
return *reinterpret_cast<uint64_t *>(&data);
}
// Count the doubles in a range, assuming double
// is IEEE 754 64-bit binary.
// Counts [start,end), including start but excluding end
uint64_t count(double start, double end) {
if (!(isfinite(start) && isfinite(end) && start <= end)) {
// Insert real error handling here
cerr << "error" << endl;
return 0;
}
if (start < 0) {
if (end < 0) {
return count(fabs(end), fabs(start));
} else if (end == 0) {
return count(0, fabs(start));
} else {
return count(start, 0) + count(0, end);
}
}
if (start == -0.0) {
start = 0.0;
}
return toInteger(end) - toInteger(start);
}
보십시오 : http://www.exploringbinary.com/the-spacing-of-decimal-floating-point-numbers/ 및 http://www.exploringbinary.com/tag/floating-point/ –
직접적인 방법은 [std :: nextafter] (http://en.cppreference.com/w/cpp/numeric/math/nextafter)를 사용하는 것입니다. – Incomputable
표현 가능한 모든 부동 소수점 값은 유리합니다 (무한대, NaN 등 제외). – Peter