Так что я пытаюсь сделать pow (x, y). Где x и y - unsigned longs, и результат сохраняется в unsigned long. Этот результат будет меньше, чем 2^63, поэтому я должен это сделать. Но поскольку он возвращает число с плавающей запятой, я получаю неточные результаты для больших чисел. Нужно ли получить точный результат без использования внешних библиотек, таких как bignum? Я знаю, что могу просто делать x * x a Y раз, но этого я пытаюсь избежать, потому что я пытаюсь сделать свою программу быстрее.Положительная точность с неподписанными длинными
ответ
Функция pow возвращает двойное значение, которое имеет проблемы с точностью, и когда вы произведете его до конца, тогда вы, несомненно, получите точность. Насколько я знаю, если вы не используете библиотеку, невозможно получить точный результат, используя только функцию pow.
Вы также можете посмотреть на Exponentiation by squaring, а также посмотреть на Barak Маноса answer где вы можете попробовать реализовать свою собственную функцию POW, как
unsigned long long pow(unsigned long long x,unsigned int y) { unsigned long long res = 1; while (y > 0) { if (y & 1) res *= x; y >>= 1; x *= x; } return res; }
Этот метод эффективен для очень больших чисел? Как 10000^10000 (x^y)? потому что я хочу держать значение под 2^63-1 все время.Поэтому я стараюсь приблизиться как можно ближе к 2^63-1, тогда я сделаю свой расчет на этой части, возьму результат и перенесу его на следующий расчет, пока мой у не станет достаточно маленьким, чтобы сделать мой расчет немедленно. – LifeisHard
@LifeisHard: '10000^10000' не меньше' 2^63', поэтому у вас возникнут другие проблемы. Помимо того, что вам понадобится (приблизительно) 125 других юниверсов для хранения всех этих цифр. – usr2564301
@Jongware: '10000^10000' больше, чем 2^63, но все равно легко поместится на веб-странице, хотя не в комментарии: '1', за которым следуют 40000' 0 '. – chqrlie
pow
по определению неточным. Он использует exp(y*log(x))
как способ эмулировать x^y
. Если вам нужна полная точность, вам нужно либо использовать внешнюю библиотеку, либо сделать свою собственную версию pow
.
Я не уверен в вашем коде. Но я думаю, что ваш код выглядит следующим образом
unsigned long x,y;
x=...//
y=...//
unsigned long res=pow(x,y);
Неправильно. Потому что pow() всегда возвращают двойной тип.
double pow(double x, double y)
вот почему у вас есть номер двойного типа.
Чтобы получить правильный номер, который вы можете сделать так:
unsigned long x,y;
x=...//
y=...//
unsigned long res=(unsigned long)pow(x,y);
Это не решает проблему OP: «поскольку он возвращает число с плавающей запятой, я получаю неточные результаты для больших чисел». – usr2564301
@ Jongware вы уверены, что значение ** res ** является числом с плавающей запятой. –
Ваше объяснение в замешательстве: до тех пор, пока 'pow' правильно объявлен с помощью' #include
Где ваш код? Вероятно, вам нужно округлить float до ближайшего целого числа. – owacoder
'pow' does' exp (y * log (x)) ', который работает быстро, но имеет проблемы с точностью. –
Это может вас заинтересовать: https://en.wikipedia.org/wiki/Exponentiation_by_squaring – szczurcio