Округление результата деления на ближайшее целое число равно pretty simple. Но я пытаюсь округлить результат деления, так что последующая операция даст наилучшее приближение. Это лучше всего объяснить простой функции:Round y = x * x до ближайшего
const int halfbits = std::numeric_limits<unsigned int>::digits/2;
unsigned x = foo(); // Likely big.
unsigned x_div = x >> halfbits; // Rounded down
unsigned y = x_div * x_div; // Will fit due to division.
Я могу округлить x_div
до ближайшего добавлением 1<<(halfbits-1)
. Но так как x² не является линейной функцией, y вообще не округляется правильно. Есть ли простой и более точный способ расчета (x*x) >> (halfbits*2)
без использования больших типов?
Я думаю, что добавление 3<<(halfbits-3)
в x_div улучшает округление, но не может доказать, что это лучшее решение. Кроме того, может ли это быть обобщено для xⁿ?
Редактировать: по многочисленным просьбам Я беру на себя смелость «переводить» вопрос в чистых арифметических терминах (ни одна из этих бит-сдвигающих вещей ...).
Примечание: все деления после этого являются целыми делениями, например 13/3 будут 4.
Проблема: мы не можем вычислить x^2, потому что x большой, поэтому вместо этого мы хотели бы вычислить (x^2)/(2^N).
Для этого вычислим
x_div = X/SQRT (2^N)
, который мы тогда площадь:
у = x_div * x_div
Однако этот результат, как правило, не хватает точного значения (x^2)/(2^N)
и ОП предлагает добавить 0,5 * sqrt (2^N) или, может быть, 0,375 * sqrt (2^N), чтобы лучше приблизиться к результату ...
Как ответ Oli Charlesworth
предлагает гораздо лучший способ добраться до фактическое значение, считая x^2
as (x_hi + x_lo)^2.
Я не потерялся с бит-операциями, но разве вы могли бы перефразировать операции в математическом центре и менее ориентированном? Я не пытаюсь быть педантичным, я просто думаю, что это поможет прояснить проблему и помочь заявить о своей цели. –
Несколько вещей, которые нужно попробовать: 'x_div_down * x_div_up',' x_div_near * x_div_near'. Если вы готовы потратить время, вы можете вычислить '(x_div * x_rest) >> (halfbit-1)' и исправить результат. –
Итак, чтобы быть ясным, подразумеваемым вашим '(x * x) >> (halfbits * 2)', вы действительно хотите * un-rounded * бит-точный результат этого? Или вы хотите, чтобы математический результат округлился правильно? – hyde