Я знаю, я знаю, люди, вероятно, скажут «просто переключиться на плавучую точку», но в настоящее время это не вариант из-за характера проекта, который Я работаю. Я помогаю писать язык программирования на C++, и в настоящее время у меня возникают трудности с попыткой получить очень точный алгоритм умножения, в результате которого у меня есть виртуальная машина, и в основном операции для mod/smod, div/sdiv (т.е. подписанные числа не являются проблемой здесь), mul, число в два раза для полных дробных чисел и число сдвинутого сдвига, которое я умножаю и разделяю, чтобы создать свое смещение. Для простоты, скажем, я работаю с 32-байтным пространством. Мои алгоритмы отлично работают для всего, что связано с целыми числами, просто когда моя дробная часть получает более 16 байтов, которые я сталкиваюсь с проблемами с точностью, и если бы я был вокруг нее, число было бы довольно точным, но я хочу, чтобы это как насколько это возможно, даже готовы пожертвовать небольшим успехом для него, если он остается неподвижным и не переходит в землю с плавающей точкой. Алгоритмы, с которыми я связан, я опишу в виде псевдокода. Было бы интересно узнать, как я могу сделать это лучше, или какие-либо соображения относительно того, почему по законам вычислительной науки то, о чем я прошу, является бесплодным делом.Какой лучший алгоритм умножения для фиксированной точки, где необходима точность
для полных дробных чисел (все байты являются дробно):
A = num1/halfShift //truncates the number down to 16 so that when multiplied, we get a full 32 byte num
B = num2/halfShift
finalNum = A * B
Для остальной части моих чисел, которые больше, чем 16 байт Я использую этот алгоритм:
this algorithm can essentially be broken down into the int.frac form
essentially A.B * C.D taking the mathematic form of
D*B/shift + C*A*shift + D*A + C*B
if the fractional numbers are larger than the integer, I halve them, then multiply them together in my D*B/shift
just like in the fully fractional example above
Есть ли какое-то метода «магического» округления, о котором я должен знать? Пожалуйста, дайте мне знать.
Алгоритм. Слово «алгоритм». Это чье-то имя. – EJP
'A = num1/halfShift // обрезает число до 16' - как только вы уменьшите« точность »(разрешение, действительно) ввода (до 16 здесь и единицы (байты/цифры/бит/слова ...) еще меньше), _no_ количество точной арифметики может восстановить/увеличить его. Вместо этого выберите, сколько «защитных мест» вам понадобится (скажем, 2) и вычислите выбранную точность (32 + 2 = 34 в этом случае). В случае умножения это позволяет снизить почти половину частичных продуктов. От округлой до конечной точности. – greybeard
@greybeard, что вы подразумеваете под «охранными местами»? –