Помощь новичкам


#2444

Почему тогда при выполнении кода

begin
  var bi:BigInteger:=BigInteger(real.MaxValue+1);
  Writeln(real(bi));
end.

выводится “1.79769313486232E+308”, а не знак бесконечности?


#2445

Потому что эта единица в значащие цифры типа real не попадает. Попробуйте так:

begin
  println(real.MaxValue);
  println(real.MaxValue + 1e291);
  println(real.MaxValue + 1e292);
end.

#2446

Кстати, если весь объём видимой части Вселенной разбить на “кубики” с ребром, равным планковской длине (на этих масштабах мы не знаем, есть ли привычное нам пространство и время), то получится порядка 1е184. Другими словами, таких чисел нет в природе. И если Вам они понадобились в реальном проекте, то что-то у Вас не так… Если для общего развития, то другое дело.


#2447

Кстати, real.MaxValue + 1e291 = real.MaxValue + 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ≠ real.MaxValue + 1, не так ли?


#2448

Потому что вы опять преобразовываете уже после операции. А real.MaxValue+1 вообще не срабатывает потому что точность real становится меньше на больших значениях.


#2449

Я по-прежнему не понял - ответа ведь мы так и не получили, - для чего @Just_name уж какой день подряд морочит нам голову ограничением real.MaxValue? 10^185 объём видимой вселенной с точки зрения планковских величин. Это безумная величина, но и она на 130 порядков меньше ограничения real.MaxValue. При этом, задавая вопрос, вместо ответа на него мы получаем новые вопросы. Не является ли все это примитивной формой троллинга, основанной на известном изречении “Один дурак может задать столько вопросов, что и 99 мудрецов не ответят”? Это без перехода на личности, а лишь о том, что берется в основу подобных троллингов. Буду рад, если ошибаюсь.


#2450

Дело в том, что я боюсь, что в моей программе расчёты будут неправильными: если любая из многих переменных типа BigInteger, хранящая сумму оценок, превысит MaxReal и если произойдёт деление типа

var СреднееАрифметическое:real:=real(переменная, значение которой больше MaxReal)/real(КоличествоОценокТожеВBigInteger);

В заключительной части это может произойти в любом случае только через час непрерывной работы программы, но в середине кода программы есть проблемное место, где это может произойти очень легко, так как пользователь собственноручно может ввести в задействованные переменные неограниченно большое целое:

...
var
  Желаемая, СреднееАрифметическоеОценок, СколькоБудетПриДобавлении5, СколькоБудетПриДобавлении4, СколькоБудетПриДобавлении3, СколькоБудетПриДобавлении2: real;
  ПригодныеСпособы: integer;
  ПолученныеОценки: array of integer;
  СколькоОценокПрибавлять, СуммаПолученныхОценок, СколькоОценокУжеЕсть, СколькоЕсть5, СколькоЕсть4, СколькоЕсть3, СколькоЕсть2, СколькоНужно5, СколькоНужно4, СколькоНужно3, СколькоНужно2, СуммаПолученныхОценокПриДобавлении5, СуммаПолученныхОценокПриДобавлении4, СуммаПолученныхОценокПриДобавлении3, СуммаПолученныхОценокПриДобавлении2, СчётчикПрибавленныхОценок: BigInteger;
  Выбор: boolean;
...
  begin
    //5
    ВыборTrue: Writeln('Сколько пятёрок по некоторому предмету у Вас уже есть? (Натуральное число.)');
    while not TryRead(СколькоЕсть5) or not (СколькоЕсть5>=0) do Writeln('Ошибка. Неподходящее значение.');
    //4
    Writeln('Сколько четвёрок по некоторому предмету у Вас уже есть? (Натуральное число.)');
    while not TryRead(СколькоЕсть4) or not (СколькоЕсть4>=0) do Writeln('Ошибка. Неподходящее значение.');
    //3
    Writeln('Сколько троек по некоторому предмету у Вас уже есть? (Натуральное число.)');
    while not TryRead(СколькоЕсть3) or not (СколькоЕсть3>=0) do Writeln('Ошибка. Неподходящее значение.');
    //2
    Writeln('Сколько двоек по некоторому предмету у Вас уже есть? (Натуральное число.)');
    while not TryRead(СколькоЕсть2) or not (СколькоЕсть2>=0) do Writeln('Ошибка. Неподходящее значение.');
    if real.IsInfinity(real(СколькоЕсть5*5+СколькоЕсть4*4+СколькоЕсть3*3+СколькоЕсть2*2)) then
    begin
      Writeln('Ошибка. Сумма оценок больше ', MaxReal, '. Введите значения поменьше.');
      goto ВыборTrue;
    end;
    if (СколькоЕсть5=0) and (СколькоЕсть4=0) and (СколькоЕсть3=0) and (СколькоЕсть2=0) then
    begin
      Writeln('Ошибка. Оценок нет.');
      goto ВыборTrue;
    end;
...

И ладно уж, если значение любой переменной с суммой будет намного больше MaxReal: программа просто запросит повторный ввод в переменные (см. выше), но, если значение слишком близко к MaxReal, но больше MaxReal, возможно, из-за того, что

соответствующее значение не превратится в Infinity,

if real.IsInfinity(real(СколькоЕсть5*5+СколькоЕсть4*4+СколькоЕсть3*3+СколькоЕсть2*2)) then
    begin
      Writeln('Ошибка. Сумма оценок больше ', MaxReal, '. Введите значения поменьше.');
      goto ВыборTrue;
    end;

не сработает и, следовательно, расчёты будут неправильными (с абстрактного объяснения чего я и начал данное сообщение).

В общем, мне нужен 100 % достоверный способ (которым я намереваюсь заменить real.IsInfinity) определения того, не превысило ли значение переменной с любой суммой MaxReal, для которого real.IsInfinity может не подойти (см. выше), но

(см. Помощь новичкам).


#2451

Для чего Вы тут используете BigInteger? Если каждый человек Земли каждый день будет получать по 10 оценок, за год это составит 365 х 10 х 7 700 000 000 = 28 105 000 000 000 оценок. За все время существования современной цивилизации от шумеро-вавилонской и египетской культур, а также эгейского мира (примерно 6 тыс лет) это не превысит 168 630 000 000 000 000 оценок. Такое число укладывается в int64. Даже если все они - пятерки, не получится превысить значение 843 150 000 000 000 000 набранных баллов, для чего, опять же, достаточно int64. При чем же тут BigInteger?

… от любви приключаются болезни потешные, для анекдотов, как я это называю, и вполне излечимые, если их не запустить, конечно. При чем же тут смерть? (“Обыкновенное чудо”)


#2452

Тем не менее (хотя бы “для общего развития”) есть ли


#2453

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


#2454

Тогда не используйте real. Решите сколько цифр после запятой вам надо, и храните их как последние цифры BigInteger. К примеру если вам надо 2 цифры после запятой - считайте что число BigInteger(123456) это на самом деле 1234.56. И проводите вычислений основываясь на этом утверждении.


#2455

Вообще это не правильно. Страдать фигнёй пока нет последствий - в любом деле полезно. Так появляются знания, которые в книжках не вычитаешь. Вот только надо своей головой решать задачи, а не каждый вздох на форуме спрашивать. Иначе пользы таки 0.


#2456

Значит, все же правильно. Ибо было сказано

Т.е. речь именно о форуме, а не о теоретизировании в голове.


#2457

Скучающие особы могут написать класс с представлением чисел при помощи двух BigInteger, где первое - дробная часть мантиссы, второе - порядок.


#2458

А ведь есть ещё decimal, который и был для подобного создан…


#2459

Decimal - в первую очередь, чтобы читать “денежные поля” из баз данных.


#2460

Я додумался до ещё одного варианта, который, кажется, работает!

begin
  var a:BigInteger:=(любое целое);
  if (BigInteger(MaxReal)-a<0) then Writeln('Ошибка.');
end.

… Но потом понял, что просто забыл поставить BigInteger(MaxReal) вместо просто MaxReal здесь: Помощь новичкам. Из-за этого-то у меня и не работало.

UPD:

Кроме того, при вводе в, как мне показалось, любую числовую переменную (даже типа BigInteger) в скомпилированной версии программы (в отличие от теста в самом паскале), максимальное количество цифр в числе = 254 (дальше просто не воспринимает нажатия клавиш с цифрами). Почему? (Как-то подозрительно близко к 2^8…)


#2461

А открыть и посмотреть?


#2462

Как использовать функцию ReadInteger(prompt: string): integer (именно с использованием приглашения ко вводу, т. е. prompt)?


#2463
begin
  ReadInteger('Введите число:')
end.