Предположим, что моя система - 32-битная машина. Учитывая это, если я использую long int для n > 63, я получу свое значение как 0. Как его решить?
Как найти 2 по мощности n. n находится в диапазоне от 0 до 200
Ответ 1
double
отлично умеет хранить полномочия от двух до 1023 точно. Не позволяйте кому-то сказать вам, что числа с плавающей запятой как-то всегда неточны. Это особый случай, когда это не так!
double x = 1.0;
for (int n = 0; n <= 200; ++n)
{
printf("2^%d = %.0f\n", n, x);
x *= 2.0;
}
Некоторые выходные данные программы:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
...
2^196 = 100433627766186892221372630771322662657637687111424552206336
2^197 = 200867255532373784442745261542645325315275374222849104412672
2^198 = 401734511064747568885490523085290650630550748445698208825344
2^199 = 803469022129495137770981046170581301261101496891396417650688
2^200 = 1606938044258990275541962092341162602522202993782792835301376
Ответ 2
Подождите около 256-битного компилятора, затем используйте int
: -)
Нет, серьезно, поскольку вы просто хотите начать с 1 и продолжать удваивать, лучше всего получить большую целую библиотеку, например GNU MP.
Вы сделали бы это с куском кода вроде (untested):
#include <stdio.h>
#include "gmp.h"
int main (void) {
int i;
mpz_t num;
mpz_init_set_ui (num, 1);
for (i = 0; i <= 200; i++) {
printf ("2^%d = ", i);
mpz_out_str (NULL, 10, num);
printf ("\n");
mpz_mul_ui (num, num, 2);
}
return 0;
}
Вы можете создать собственную структуру данных массива longs с двумя операциями, двойными и печатными, но я думаю, что было бы намного проще использовать GMP.
Если вы хотите бросить свои собственные, взгляните на это. Это вариация/упрощение некоторых больших целочисленных библиотек, которые я разработал в прошлом:
#include <stdio.h>
#include <stdlib.h>
// Use 16-bit integer for maximum portability. You could adjust
// these values for larger (or smaller) data types. SZ is the
// number of segments in a number, ROLLOVER is the maximum
// value of a segment plus one (need to be less than the
// maximum value of your datatype divided by two. WIDTH is
// the width for printing (number of "0" characters in
// ROLLOVER).
#define SZ 20
#define ROLLOVER 10000
#define WIDTH 4
typedef struct {
int data[SZ];
} tNum;
// Create a number based on an integer. It allocates the segments
// then initialises all to zero except the last - that one is
// set to the passed-in integer.
static tNum *tNumCreate (int val) {
int i;
tNum *num = malloc (sizeof (tNum));
if (num == NULL) {
printf ("MEMORY ERROR\n");
exit (1);
}
for (i = 0; i < SZ - 1; i++) {
num->data[i] = 0;
}
num->data[SZ-1] = val;
}
// Destroy the number. Simple free operation.
static void tNumDestroy (tNum *num) {
free (num);
}
// Print the number. Ignores segments until the first non-zero
// one then prints it normally. All following segments are
// padded with zeros on the left to ensure number is correct.
// If no segments were printed, the number is zero so we just
// output "0". Then, no matter what, we output newline.
static void tNumPrint (tNum *num) {
int i, first;
for (first = 1, i = 0; i < SZ; i++) {
if (first) {
if (num->data[i] != 0) {
printf ("%d", num->data[i]);
first = 0;
}
} else {
printf ("%0*d", WIDTH, num->data[i]);
}
}
if (first) {
printf ("0");
}
printf ("\n");
}
// Double a number. Simplified form of add with carry. Carry is
// initialised to zero then we work with the segments from right
// to left. We double each one and add the current carry. If
// there overflow, we adjust for it and set carry to 1, else
// carry is set to 0. If there carry at the end, then we have
// arithmetic overflow.
static void tNumDouble (tNum *num) {
int i, carry;
for (carry = 0, i = SZ - 1; i >= 0; i--) {
num->data[i] = num->data[i] * 2 + carry;
if (num->data[i] >= ROLLOVER) {
num->data[i] -= ROLLOVER;
carry = 1;
} else {
carry = 0;
}
}
if (carry == 1) {
printf ("OVERFLOW ERROR\n");
exit (1);
}
}
// Test program to output all powers of 2^n where n is in
// the range 0 to 200 inclusive.
int main (void) {
int i;
tNum *num = tNumCreate (1);
printf ("2^ 0 = ");
tNumPrint (num);
for (i = 1; i <= 200; i++) {
tNumDouble (num);
printf ("2^%3d = ", i);
tNumPrint (num);
}
tNumDestroy (num);
return 0;
}
и связанный с ним вывод:
2^ 0 = 1
2^ 1 = 2
2^ 2 = 4
2^ 3 = 8
2^ 4 = 16
2^ 5 = 32
2^ 6 = 64
2^ 7 = 128
2^ 8 = 256
2^ 9 = 512
: : : : :
2^191 = 3138550867693340381917894711603833208051177722232017256448
2^192 = 6277101735386680763835789423207666416102355444464034512896
2^193 = 12554203470773361527671578846415332832204710888928069025792
2^194 = 25108406941546723055343157692830665664409421777856138051584
2^195 = 50216813883093446110686315385661331328818843555712276103168
2^196 = 100433627766186892221372630771322662657637687111424552206336
2^197 = 200867255532373784442745261542645325315275374222849104412672
2^198 = 401734511064747568885490523085290650630550748445698208825344
2^199 = 803469022129495137770981046170581301261101496891396417650688
2^200 = 1606938044258990275541962092341162602522202993782792835301376
Ответ 3
Прошло много времени с тех пор, как я серьезно использовал Java, но: BigInteger class? Он имеет все обычные математические операции (multiply
, pow
) и побитовые (shiftLeft
) операции.
Тэги немного запутаны, какой язык вы предпочитаете?
Ответ 4
python поддерживает большие целые числа. В любом приглашении linux запустите это:
$ python -c "for power in range(201): print power, 2**power"
0 1
1 2
2 4
3 8
4 16
5 32
6 64
<snip>
196 100433627766186892221372630771322662657637687111424552206336
197 200867255532373784442745261542645325315275374222849104412672
198 401734511064747568885490523085290650630550748445698208825344
199 803469022129495137770981046170581301261101496891396417650688
200 1606938044258990275541962092341162602522202993782792835301376
Это можно легко сделать в script, если это необходимо. См. Любой учебник python.
Ответ 5
Используйте java.math.BigInteger.shiftLeft
.
for (int i = 0; i <= 200; i++) {
System.out.format("%d = %s%n", i, BigInteger.ONE.shiftLeft(i));
}
Выдержка output:
0 = 1
1 = 2
2 = 4
3 = 8
4 = 16
:
197 = 200867255532373784442745261542645325315275374222849104412672
198 = 401734511064747568885490523085290650630550748445698208825344
199 = 803469022129495137770981046170581301261101496891396417650688
200 = 1606938044258990275541962092341162602522202993782792835301376
Если BigInteger
недоступно, вы можете просто вручную выполнить умножение и сохранить его в String
.
String s = "1";
for (int i = 0; i < 200; i++) {
StringBuilder sb = new StringBuilder();
int carry = 0;
for (char ch : s.toCharArray()) {
int d = Character.digit(ch, 10) * 2 + carry;
sb.append(d % 10);
carry = d / 10;
}
if (carry != 0) sb.append(carry);
s = sb.toString();
System.out.format("%d = %s%n", i + 1, sb.reverse());
}
Ответ 6
В C/С++ я не знаю стандартного способа, которым вы можете хранить целые числа, для которых большое решение pax - это путь.
Однако для Java у вас есть выход, BigInteger
Ответ 7
Использовать схему!
1 => (expt 2 200)
1606938044258990275541962092341162602522202993782792835301376
Ответ 8
Если unsigned long int
- 64 бита, то наибольшее значение для 2 ^ n, которое вы можете представить, равно 2 ^ 63 (т.е. n = 63):
unsigned long int x = (1UL << n); // n = 0..63