Здравствуйте, у меня есть некоторые трудности с функцией ceil в c ++:
У меня есть регулярная сетка точек, и мне нужно выполнить интерполяцию по ней, чтобы вычислить z-значения набора точек.
Чтобы сделать это, мне нужно для каждой вычисленной точки получить ближайшие точки на сетке. Я делаю это так:
y1 = dy*floor(p.y/dy);
y2 = dy*ceil(p.y/dy);
где dy — пространство между двумя точками сетки. (y1, p.y и dy двойные)
Если я отображу результаты с помощью
cout << static_cast<double>(p.y/dy) << ": " << y1 << ", " << y2 << endl;
Я получил эти странные результаты:
0: 0, 0
1: 0.1, 0.1
2: 0.2, 0.2
3: 0.3, 0.4
Три первых результата в порядке, но последний неверен и делает утверждение ошибочным.
Хотелось бы узнать, откуда появилась эта странная ошибка и как ее избежать.
Благодарю.
Я прошу прощения за мой английский
РЕДАКТИРОВАТЬ
Я вызываю функцию с dy = 0.1, но во время выполнения она принимает следующее значение dy = 0.10000000000000001.
p.y инициализируется так:
const uint N = round((x2 - x1) / dx2);
const uint M = round((y2 - y1) / dy2);
double p = persistence;
double n = number_of_octaves;
// generation of the points where the perlin noise is generated
std::vector<Vertex3d> ret;
std::vector<Vertex3d> dummy;
for (uint i=0;i<=N;++i)
{
for (uint j=0;j<=M;++j)
{
ret.push_back({.x = i*dx2, .y=j*dy2, .z=0});
dummy.push_back({.x = i*dx2, .y=j*dy2, .z=0});
}
}
где x1 = 0 и x2 = 1 (по данным gdb)
Учитывая ваши результаты, я полагаю, dy
равно 0.1
,
Ваши результаты не ошибаются. Если у вас есть 0.3 < p.y < 0.4
тогда у вас будет 3 < p.y/dy < 4
Итак ceil
будет 4
и floor
будет 3
,
Может быть, вы запутались, потому что где-то еще в вашем коде вы установили p.y
до 0,3 или 0,4. Вы должны знать, что поплавки не так точно. Это означает, что даже если вы установите p.y = 0.3
это может иметь значение 0.30000001
или что-то подобное, вызывая вашу проблему.
Когда вы используете арифметику с плавающей запятой, вы, как правило, не должны полагаться на то, что результат будет точно целым числом из-за неточности в вычислениях с плавающей запятой. Вам, вероятно, нужно изменить дизайн своего кода, чтобы он не зависел от этого.
Это выглядит просто как случай ошибок округления для арифметики с плавающей запятой.
Возможно, в последнем случае результат равен 3.00000000000001, поэтому его потолок равен 4, а не 3 (а затем умножается на 0,1).