Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Большие числа в Python и C++  (Прочитано 10000 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Jack Sparrow

  • Автор темы
  • Активист
  • *
  • Сообщений: 641
    • Просмотр профиля
Большие числа в Python и C++
« : 30 Июля 2013, 01:01:38 »
Вычисляем факториал в Питоне:
Код: (Python) [Выделить]
def factorial(n):
    if n == 0:
        return 1
    else:
    return n * factorial (n - 1)

for n in range(40):
    print n, '\t', factorial(n)
Получаем такой результат:
0     1
1     1
2     2
3     6
4     24
5     120
6     720
7     5040
8     40320
9     362880
10     3628800
11     39916800
12     479001600
13     6227020800
14     87178291200
15     1307674368000
16     20922789888000
17     355687428096000
18     6402373705728000
19     121645100408832000
20     2432902008176640000
21     51090942171709440000
22     1124000727777607680000
23     25852016738884976640000
24     620448401733239439360000
25     15511210043330985984000000
26     403291461126605635584000000
27     10888869450418352160768000000
28     304888344611713860501504000000
29     8841761993739701954543616000000
30     265252859812191058636308480000000
31     8222838654177922817725562880000000
32     263130836933693530167218012160000000
33     8683317618811886495518194401280000000
34     295232799039604140847618609643520000000
35     10333147966386144929666651337523200000000
36     371993326789901217467999448150835200000000
37     13763753091226345046315979581580902400000000
38     523022617466601111760007224100074291200000000
39     20397882081197443358640281739902897356800000000

Теперь вычисляем в C++
Код: (C++) [Выделить]
#include <iostream>
using namespace std;

long factorial (long n)
{
    if (n > 1)
        return (n * factorial (n - 1));
    else
        return 1;
}
int main () {
   
    long n;
    for (n = 0; n < 40; n++)
        cout << n << '\t' << factorial(n) << endl;
   
    return 0;
}
Результат такой:
0    1
1    1
2    2
3    6
4    24
5    120
6    720
7    5040
8    40320
9    362880
10    3628800
11    39916800
12    479001600
13    6227020800
14    87178291200
15    1307674368000
16    20922789888000
17    355687428096000
18    6402373705728000
19    121645100408832000
20    2432902008176640000
21    -4249290049419214848
22    -1250660718674968576
23    8128291617894825984
24    -7835185981329244160
25    7034535277573963776
26    -1569523520172457984
27    -5483646897237262336
28    -5968160532966932480
29    -7055958792655077376
30    -8764578968847253504
31    4999213071378415616
32    -6045878379276664832
33    3400198294675128320
34    4926277576697053184
35    6399018521010896896
36    9003737871877668864
37    1096907932701818880
38    4789013295250014208
39    2304077777655037952

До 20! все одинаково. Потом, как я понимаю, у С++ начинается мусор.
Причина, вероятно, в том, что размерности long не хватает. В принципе, можно сделать unsigned long, но это тоже мало помогает. Исчезают отрицательные величины, но все равно они неправильные. У меня возникает два вопроса:

1) Можно ли в С++  выводить числа большей разрядности?
2) Почему выводится мусор, а не сообщение об ошибке? Ведь это потенциально опасно.

Ну или может быть тут что-то совсем другое?
Нейросети тебя не заменят. Тебя заменит человек, который умеет ими пользоваться.

Оффлайн peregrine

  • FSM
  • СуперМодератор
  • Старожил
  • *
  • Сообщений: 7215
  • Gentoo x64 Ubuntu 16.04.1 x64
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #1 : 30 Июля 2013, 01:11:42 »
Jack Sparrow, идеология языка такая, может быть и неправильный выбор, но программист сам вправе делать его.
long long int попробуйте.
А вообще для очень-очень больших чисел нужны отдельные библиотеки. Вот это посмотрите.
« Последнее редактирование: 30 Июля 2013, 01:17:23 от peregrine »

Оффлайн Jack Sparrow

  • Автор темы
  • Активист
  • *
  • Сообщений: 641
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #2 : 30 Июля 2013, 03:47:04 »
Да, с библиотеками, конечно, понятно. Другой вопрос - почему предупреждение не выдается? Например, если у меня задать n = 100, то после 65 вообще все нули выводятся. В Питоне в подобном случае будет сообщение, что достигнута максимальная глубина рекурсии. А С++, как я вижу, расслабиться не дает.
Нейросети тебя не заменят. Тебя заменит человек, который умеет ими пользоваться.

Оффлайн Чистый

  • Почётный модератор
  • Старожил
  • *
  • Сообщений: 3473
  • nix - вот оно счастье...
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #3 : 30 Июля 2013, 09:17:21 »
Да, с библиотеками, конечно, понятно. Другой вопрос - почему предупреждение не выдается? Например, если у меня задать n = 100, то после 65 вообще все нули выводятся. В Питоне в подобном случае будет сообщение, что достигнута максимальная глубина рекурсии. А С++, как я вижу, расслабиться не дает.


C/C++ cчитает что тот кто его использует достаточно квалифицирован, что бы писать качественный код, еже ли нет, то это уже проблемы самого программиста а не языка... лопатой тоже можно руку отрубить :)
Тестовый репозиторий kdeNeur ppa:devcode/kdeneur
各々が死ぬことをどのように決定する

Оффлайн peregrine

  • FSM
  • СуперМодератор
  • Старожил
  • *
  • Сообщений: 7215
  • Gentoo x64 Ubuntu 16.04.1 x64
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #4 : 30 Июля 2013, 13:49:03 »
Jack Sparrow, иногда может быть нужен и мусор, вот так его тоже можно костыльно получать, чтоб тормозило, наверно в Windows так и написано. :)
Шутка конечно, но полностью согласен с Чистый, о чём писал и сам, когда говорил про идеологию языка C++. Вообще, если не чайник в программировании Бьёрна Страуструпа почитайте, меньше вопросов глупых будет, но если не читали никого другого по C++, то запутаться можно. Начинать с него не лучший выбор.

Оффлайн inkblack

  • Старожил
  • *
  • Сообщений: 1216
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #5 : 30 Июля 2013, 14:35:44 »
Джек, всё правильно. Так и должно быть.
Когда вы в Си пишете
Код: (C) [Выделить]
{
 long n=1;
 // ... 
 n *= 2;
 // ... 
 }
то подразумевается, что вы знаете, что делаете.
Для n отводится 32 или 64 двоичных разряда,
а ваша задача — позаботиться о том, чтобы результат
в них поместился. Выражение «умножить n на 2»
переводится в одну команду процессора. В этом месте Си
практически не отличается от Ассемблера. Про него и сказано,
что это язык низкого уровня.

Питон — совсем другое дело. Переменные там хранятся в
виде, который зависит от их значения, производятся
постоянные проверки, чтобы не было переполнения и т. д.
В Питоне по поводу n * 2 выполняется огромная куча
действий. Язык высокого уровня делает за вас всю
тягомотную рутинную работу. И выдаёт предупреждения.

Но! Обычно и даже очень часто это не нужно.
В программах переменные, имеющие целые значения
весьма редко достигают величин, опасно приближающихся
к 2^31 или 2^63. Поэтому возможные неудобства — не такая уж
большая плата за простоту реализации и выигрыш в скорости.

Т. е., если у вас произошло переполнение при умножении
целых чисел, то либо вы должны были это предвидеть и
позаботиться заранее, как в примере с факториалом,
либо этого не должно было случиться. Значит, у вас ошибка
в программе или алгоритме, тут и Питон не поможет,
надо её исправлять. Хотя искать с Питоном проще.
« Последнее редактирование: 30 Июля 2013, 14:40:43 от inkblack »
Делюсь знаниями, но их у меня мало!

Оффлайн alexander.pronin

  • Старожил
  • *
  • Сообщений: 2539
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #6 : 30 Июля 2013, 15:38:54 »
... искать с Питоном проще.
Причина простая.
В С int - это внутренняя переменная. Вся забота о всяких исключениях ложится на того, кто пишет программу.
В Питон int - это объект некоторого класса "int". Т.е. кроме собственно переменной есть методы записи в сам объект, которые могут проверять на что-то  (например, на переполнение, не соответствие и т.д.)и генерировать исключения.
Как-то так или почти так.
Такие же фокусы есть в C# и Java.

Оффлайн Jack Sparrow

  • Автор темы
  • Активист
  • *
  • Сообщений: 641
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #7 : 30 Июля 2013, 19:59:48 »
В принципе оно и понятно. С чего тогда С/С++ быть быстрым? Ведь не специально же понижают скорость у всяких там питонов.

PS. А со Страуструпом я разберусь. Закончу сначала с Липпманом.
Нейросети тебя не заменят. Тебя заменит человек, который умеет ими пользоваться.

Оффлайн alex312

  • Новичок
  • *
  • Сообщений: 1
    • Просмотр профиля

Оффлайн Jack Sparrow

  • Автор темы
  • Активист
  • *
  • Сообщений: 641
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #9 : 02 Августа 2013, 13:34:27 »
Кстати, о Boost. О нем слышал противоречивые мнения. С одной стороны, говорят, хорошо, много разных хороших библиотек, которые со временем должны стать стандартными. С другой стороны, есть и противники, которые считают, что нужно стараться обходиться стандартными библиотеками, чтобы не тянуть зависимостей.

Но это ладно. Меня больше всего интересует целесообразность того, что в C/C++ не возникают исключения при подобных случаях. Например, я только что поделил 5 на 0 и получил ответ 1606416584. Мой IDE предупредил, что значение не определено, но компилятор проглотил.

1) Если это связано с тем, что подобные проверки снижают скорость вычислений, поэтому забота о безопасности перекладывается на плечи программиста, чтобы скорость оставалась высокой, то это мне было бы понятно.

2) Но если это просто так, эдакий снобизм, мол, раз программируешь на C++, то не должен допускать подобные глупости, а если делаешь, то ССЗБ, то это было бы не понятно.
Нейросети тебя не заменят. Тебя заменит человек, который умеет ими пользоваться.

Оффлайн Чистый

  • Почётный модератор
  • Старожил
  • *
  • Сообщений: 3473
  • nix - вот оно счастье...
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #10 : 02 Августа 2013, 14:27:26 »
Jack Sparrow,
еще очень многое зависит от компилятора, но вы должны смириться с тем что если уж вы пишите на С++, то будьте готовы сами заботится о том что бы ничего подобного не случилось... т.е. вы ССЗБ
Тестовый репозиторий kdeNeur ppa:devcode/kdeneur
各々が死ぬことをどのように決定する

Оффлайн inkblack

  • Старожил
  • *
  • Сообщений: 1216
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #11 : 02 Августа 2013, 15:42:55 »
Джек, природа такого поведения не в заботе о быстродействии, скорее, это
свойство языка низкого уровня. Повторюсь, в этом месте вы пишете на слегка
оптимизированном ассемблере. Практически, именно так.

Правила выполнения арифметических операций в Си повторяют правила выполнения
команд процессора. Поскольку процессоры, вообще говоря, разные, результаты
деления на ноль, умножения слишком больших чисел и других операций, в которых
невозможно получить правильный результат, будут отличаться при выполнении
одной и той же программы на разных процессорах. Насколько я помню, в стандарте
прямо об этом говорится.

... Например, я только что поделил 5 на 0 и получил ответ 1606416584. Мой IDE предупредил, что значение не определено, но компилятор проглотил.

Странный у вас компилятор. У меня так:
Код: (bash) [Выделить]
sol@eee:~/backgrounds$ make dive
cc     dive.c   -o dive
sol@eee:~/backgrounds$ ./dive
Исключение в операции с плавающей точкой (сделан дамп памяти)
А исходник такой:
Код: (c) [Выделить]
sol@eee:~/backgrounds$ cat dive.c
#include <stdio.h>

int five(void) {return 5;}
int zero(void) {return 0;}

int main(void) {
 printf("%d\n",five()/zero());
 return 0;
 }

А если написать не five()/zero(), а 5/0, то и компилятор предупредит:
Код: (bash) [Выделить]
dive.c:8:17: предупреждение: деление на ноль [-Wdiv-by-zero]Может быть, конечно, дело в том, что у меня Си, а у вас Плюсы.

Ну и конечно же, это никакой не снобизм. В стандарте, я уже говорил,
об этом предупреждают. И ведь любой инструмент, даже самый лучший в мире,
всё равно имеет ограниченную область применения. Сапожным ножом неудобно
откручивать шурупы, отвертка не заменит резец для токарного станка.
Делюсь знаниями, но их у меня мало!

Оффлайн Jack Sparrow

  • Автор темы
  • Активист
  • *
  • Сообщений: 641
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #12 : 02 Августа 2013, 18:29:30 »
У меня что C, что C++, разницы особой нет. Вообще-то я работаю на Маке в Xcode. Также пробовал в Qt Creator. Результаты одинаковые. Потом попробовал скомпилировать из командной строки разными компиляторами: gcc и cc (cc, как я понял, то же самое, что и clang). Везде один результат:
а) выдается предупреждение о делении на ноль
б) компиляция проходит успешно
в) при выполнении выдается некоторое целое число.

Попробовал на Убунте. Тоже выдается предупреждение и сообщение об удачной компиляции, но при выполнении да, выдается исключение Floating point exception (core dumped). Никакого числа не выводится.

Возможно зависит от версии компилятора. На Маке он староват - 4.2.1, а на Убунте поновее - 4.6.3.
Нейросети тебя не заменят. Тебя заменит человек, который умеет ими пользоваться.

Оффлайн SergeyIT

  • Зануда.
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 5743
  • Все по палатам!
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #13 : 02 Августа 2013, 19:10:05 »
Jack Sparrow,
Какая цель - делить на ноль?
Извините, я все еще учусь

Оффлайн Jack Sparrow

  • Автор темы
  • Активист
  • *
  • Сообщений: 641
    • Просмотр профиля
Re: Большие числа в Python и C++
« Ответ #14 : 02 Августа 2013, 21:00:19 »
Jack Sparrow,
Какая цель - делить на ноль?
Опыта особого в С/С++ у меня нет. Я все больше с Питоном играюсь. Решил вычислить факториал в Питоне и С++. Увидел, что С++ не указывает на ошибку, а продолжает вычисления, выдавая мусор. Вот мне и интересно стало узнать, в каких случаях С++ генерирует исключения. А деление на ноль это лишь другой пример. Я был уверен, что уж в этом-то случае компилятор откажется генерировать код, а он, как видно, не отказался.

Я ни в коем случае не критикую С++. Просто мне хочется понять логику, а также подход к разработке.

Допустим, я работаю с большими данными. Я выбираю максимально большой встроенный тип данных. По ходу работы мне нужно перемножить две величины. Может оказаться и так, что результат будет превышать максимально допустимый. Могу ли я знать это заранее? Ведь моя программа работает с переменными величинами (нет никакой программы, это я для примера). Значит, мне нужно написать какую-то функцию, которая будет предварительно проверять величины и выдавать сообщение, если результат будет выходить за пределы. Или что-то подобное. Разве не так, если это ответственность программиста? Ну как, например, я могу знать заранее, что 20! можно вычислить в С++ стандартными методами, а 21! уже нельзя? Я и ошибку-то заметил совершенно случайно, и то лишь благодаря тому, что вывел данные столбиком: каждое последующее число было на одну-две цифры длиннее предыдущего, видно зрительно. А если бы я не выводил все числа столбиком, а вычислял бы произвольный член? Например, n!. Ввел бы 21 и получил бы результат, и не знал бы, что он неверный. Кстати, если в этой моей С++шной программе задать тип unsigned long, то и 21!, и 22! будут больше предыдущих, а потом уже начинается лажа, хотя и 21!, и 22! тоже неверные.

Если бы результат превысил бы long и было бы выдано исключение, то мне было бы все понятно, ну, мол, язык достаточно низкоуровневый. А так выводится какое-то другое правдоподобное число, и ты остаешься в приятном заблуждении, что открыл новый закон природы, тогда как тебе просто как программисту нужно руки отбить линейкой.
(Нажмите, чтобы показать/скрыть)
Нейросети тебя не заменят. Тебя заменит человек, который умеет ими пользоваться.

 

Страница сгенерирована за 0.027 секунд. Запросов: 21.