Помощь - Поиск - Пользователи - Календарь
Полная версия: Числа Смита
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Relrin
Видел здесь в FAQ решение для супер-чисел Смита решение в виде функций. Так вот, мне подкинули похожую задачку, только сказали чтобы делать ее без функций... Прошу помощи! wacko.gif

Чуть не забыл, про условие задачи: Составное число называется числом Смита, если сумма его цифр равна сумме цифр всех чисел, образующихся разложением исходного числа на простые множители. Число Смита называется супер-числом Смита, если сумма его цифр является числом смита. Найти супер-число Смита с номером N, являющееся полным квадратом. (Число называется полным квадратом, если корень квадратный из него является простым числом)

Проблема в коде ниже в том, что у меня находит числа до 6(N=6) включительно, а это число 10201, а дальше не хватает "числового пространства". Плюс смущает его получение числа из под корня... Из числа 22, или 202 или 1111, например, как результаты поиска таких супер-чисел, целое число не получается, но его программа считает как целое...

Мое решение:

Var
Found,SFound : boolean; {Флаг для цикла}
simple : boolean; {Флаг, используемый при проверке на пр. число}
square : double; {Переменная,в котором хранится число из кв. корня}
number,numb : integer; {Число,с которого начинаем поиск...}
N : integer; {Наше супер-число Смита}
i,j,k : integer; {Счетчики для циклов}
Smith, SSmith : integer; {Искомое супер-число Смита}
SumNumb : integer; {Сумма цифр числа}
SumSubs : integer; {Сумма множителей}
amount : integer; {Кол-во простых множителей}
numSum,numSub : integer; {Переменные для поиска сумм}
factor,pr : integer; {Начальный делитель числа}
s,sfact,sum : integer; {Результат вычислений}

Begin
{ВВОД ЧИСЛА N}
write('Enter your number N: ');
readln(N);
{Поиск супер-числа Смита}
i:=0;
number:=1;
while i<>N do
begin
repeat
SFound:=false;
{Поиск числа Смита}
repeat
inc(number);
Found:=false;
SumNumb:=0;
SumSubs:=0;
numSum:=number;
numSub:=number;
{Подсчет суммы цифр числа}
s:=0;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SumNumb:=s;
{Подсчет суммы множителей числа}
s:=0;
factor:=2;
amount:=0;
repeat
if (numSub mod factor)=0 then
begin
{Подсчитываем сумму цифр числа (множителя)}
sfact:=0;
numb:=factor;
while numb<>0 do
begin
inc(sfact,numb mod 10);
numb:=numb div 10;
end;
sum:=sfact;
{Подсчитываем сумму множителей}
s:=s+sum;
inc(amount);
numSub:=numSub div factor
end
else inc(factor);
until numSub=1;
SumSubs:=s;
{Найденное число - это число Смита?}
{Проверяем, чтобы сумма его цифр была равна сумме простых множителей}
if ((SumNumb=SumSubs) and (amount>1)) then Found:=true;
until Found=true;
{Поиск супер-чисел Смита, удолетворяющих условиям}
{Подсчет суммы цифр cупер-числа Смита}
s:=0;
numSum:=0;
numSum:=number;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SSmith:=s;
{Проверка на супер-число Смита}
SumNumb:=0;
SumSubs:=0;
numSum:=SSmith;
numSub:=SSmith;
{Подсчет суммы цифр числа}
s:=0;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SumNumb:=s;
{Подсчет суммы множителей числа}
s:=0;
factor:=2;
amount:=0;
repeat
if (numSub mod factor)=0 then
begin
{Подсчитываем сумму цифр числа (множителя)}
sfact:=0;
numb:=factor;
while numb<>0 do
begin
inc(sfact,numb mod 10);
numb:=numb div 10;
end;
sum:=sfact;
{Подсчитываем сумму множителей}
s:=s+sum;
inc(amount);
numSub:=numSub div factor
end
else inc(factor);
until numSub=1;
SumSubs:=s;
{Теперь еще проверим,чтобы это из корня кв. было простым числом}
square:=sqrt(SSmith);
simple:=true;
if frac(square)=0 then
begin
simple:=true;
for j:=2 to round(sqrt(square)) do
if (round(square) mod j)=0 then simple:=false;
end
else simple:=false;
{Найденное число - это супер-число Смита?}
{Проверяем, чтобы сумма его цифр являлась числом Смита}
if ((SumNumb=SumSubs) and (amount>1) and (simple=true)) then SFound:=true;
until SFound=true;
inc(i);
end;
Smith:=number;
{ВЫВОД СУПЕР-ЧИСЛА СМИТА}
writeln('Ваше супер-число Смита: ',Smith);
readln;
End.

volvo
Цитата
а дальше не хватает "числового пространства"
А ты в FAQ-е функцию внимательно посмотри, значение какого типа она возвращает? Там же хватает "числового пространства", так ведь? Вот и используй тот же тип при вычислениях.
Relrin
Цитата(volvo @ 4.11.2010 19:53) *

А ты в FAQ-е функцию внимательно посмотри, значение какого типа она возвращает? Там же хватает "числового пространства", так ведь? Вот и используй тот же тип при вычислениях.

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


{Теперь еще проверим,чтобы это из корня кв. было простым числом}
square:=sqrt(SSmith);
simple:=true;
if frac(square)=0 then
begin
simple:=true;
for j:=2 to round(sqrt(square)) do
if (round(square) mod j)=0 then simple:=false;
end
else simple:=false;

volvo
Цитата
Мы возвращаем целое число.
Целые числа бывают РАЗНЫЕ. Разной емкости. Бывает Байт, который хранит значения 0 - 255, бывает Integer, который хранит -31768 .. 32767, а бывает тот тип, который использовал я - LongInt, который хранит значения до двух миллиардов.

Еще одна проблема - это то, что высказывание
Цитата
у меня находит числа до 6(N=6) включительно, а это число 10201
не является правдой. 10201 это третий СуперСмит, который является полным квадратом, а не шестой.

Добавлено через 4 мин.
Цитата
Число называется полным квадратом, если корень квадратный из него является простым числом
Неправильно. Полный квадрат - это число, квадратный корень из которого является целым числом. В таком случае проверка SSmith на полный квадрат сводится к одной строке:
isFullSqr := (Sqr(Trunc(Sqrt(SSmith))) = SSmith);
Relrin
Цитата(volvo @ 4.11.2010 20:14) *

Добавлено через 4 мин.
Неправильно. Полный квадрат - это число, квадратный корень из которого является целым числом. В таком случае проверка SSmith на полный квадрат сводится к одной строке:
isFullSqr := (Sqr(Trunc(Sqrt(SSmith))) = SSmith);


Ммм.... А где это заменить в этом коде? Всмысле что на что заменить, чтобы условие выполнялось? А то если заменить, этот кусочек кода вместо предыдущей проверки на полный квадрат, то программа просто выводит супер-числа Смита... blink.gif
TarasBer
> где это заменить в этом коде?

Палишься.

Спроси у того, кто код писал.
Relrin
Цитата(TarasBer @ 4.11.2010 21:11) *

> где это заменить в этом коде?

Палишься.

Спроси у того, кто код писал.

Ничего я не палюсь, не неси чепухи smile.gif
Код писал я и та подстановка:

isFullSqr := (Sqr(Trunc(Sqrt(SSmith))) = SSmith);


Она не подходит под условие задачи... Потому что возвести в квадрат то число, из которого мы извлекали корень ничего не меняет... Мы получим то же самое число. То есть у нас не будет проверки тут на то, какое число - простое и составное...
TarasBer
Что делает Trunc - знаешь?
Вот примени этот код для числа 5.
volvo
Цитата
То есть у нас не будет проверки тут на то, какое число - простое и составное...
Опять он за свое. Тебе НЕ НАДО проверять простоту числа, пойми это. Тебе надо проверить, что возведение целой части корня в квадрат дает то же число, а не меньшее. Всё. Этого достаточно, чтобы число являлось полным квадратом.
Relrin
Цитата(TarasBer @ 4.11.2010 21:38) *

Что делает Trunc - знаешь?
Вот примени этот код для числа 5.

Знаю конечно для чего, как правило для дробный чисел используют, чтобы получить целое, путем "отсекания" дробной части smile.gif
TarasBer
> Потому что возвести в квадрат то число, из которого мы извлекали корень

Если ты знаешь, что такое Trunc, то почему ты говоришь "то число, из которого извлекали"? Не, не то число, другое, округлённое.

Админ, кнопки сломались, Опера 9.26
Relrin
Цитата(TarasBer @ 4.11.2010 21:50) *

Если ты знаешь, что такое Trunc, то почему ты говоришь "то число, из которого извлекали"? Не, не то число, другое, округлённое.

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

Вообщем пока получилось так:

{Проверка для супер-числа Смита}
//square:=sqrt(SSmith);
if sqr(trunc(sqrt(SSmith))=SSmith then simple=true
else
simple:=false;



Для проверки я указал N=2, результат - ^C ...
TarasBer
> Ну, попробуй тогда сначала под корень число 22 занести, потом в квадрат занести - сомневаюсь, что будет такое же число, как до вычислений.

Офигеть, а в 7 посте ты что говорил?

> Код писал я и та подстановка [...] не подходит под условие задачи... Потому что возвести в квадрат то число, из которого мы извлекали корень ничего не меняет... Мы получим то же самое число.

Relrin
Ну, я немного изменил условия проверки, чтобы подходило под

sqr(trunc(sqrt(SSmith))=SSmith


И получил так:

square:=sqrt(SSmith);
s:=0;
for k:=1 to trunc(square) do
begin
s:=sqr(k);
if s=SSmith then simple:=true
else simple:=false;
end;


Только у меня никак не получается так, чтобы число 10201 было третьим супер-числом Смита, соответствующие условию задачи. У меня получается, что третьим таким числом будет 121, вторым - 22. Ну тут у меня получилось так, что я вернулся к тому, с чего начал... sad.gif
TarasBer
22 не является полным квадратом, оно не подходит.
Как проверять число на полную квадратность - тебе сказали.
В чём проблема?
Relrin
Цитата(TarasBer @ 4.11.2010 22:37) *

22 не является полным квадратом, оно не подходит.
Как проверять число на полную квадратность - тебе сказали.
В чём проблема?

Да не получается что-то...
В проверке пришел к такому коду:

isFullSqr := (Sqr(Trunc(Sqrt(SSmith))) = SSmith);
if isFullSqr=true then simple:=true;


Но результаты, что и в предыдущем посте получаются... sad.gif
TarasBer
После проверки с разложением на простые множители допиши
if Sqr(Trunc(Sqrt(SSmith))) <> SSmith then simple:=false;

И не надо использовать бульшит.

if a=false успешно заменяется на if not a, а такая конструкция, как if a = true then b := true else b := false, увековечена на говнокоде, потому что можно просто написать b := a;
Relrin
Цитата(TarasBer @ 4.11.2010 23:03) *

После проверки с разложением на простые множители допиши
if Sqr(Trunc(Sqrt(SSmith))) <> SSmith then simple:=false;

И не надо использовать бульшит.

if a=false успешно заменяется на if not a, а такая конструкция, как if a = true then b := true else b := false, увековечена на говнокоде, потому что можно просто написать b := a;


Дописал, но происходит зацикливание программки...


Begin
{ВВОД ЧИСЛА N}
write('Enter your number N: ');
readln(N);
{Поиск супер-числа Смита}
i:=0;
number:=1;
while i<>N do
begin
repeat
SFound:=false;
{Поиск числа Смита}
repeat
inc(number);
Found:=false;
SumNumb:=0;
SumSubs:=0;
numSum:=number;
numSub:=number;
{Подсчет суммы цифр числа}
s:=0;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SumNumb:=s;
{Подсчет суммы множителей числа}
s:=0;
factor:=2;
amount:=0;
repeat
if (numSub mod factor)=0 then
begin
{Подсчитываем сумму цифр числа (множителя)}
sfact:=0;
numb:=factor;
while numb<>0 do
begin
inc(sfact,numb mod 10);
numb:=numb div 10;
end;
sum:=sfact;
{Подсчитываем сумму множителей}
s:=s+sum;
inc(amount);
numSub:=numSub div factor
end
else inc(factor);
until numSub=1;
SumSubs:=s;
{Найденное число - это число Смита?}
{Проверяем, чтобы сумма его цифр была равна сумме простых множителей}
if ((SumNumb=SumSubs) and (amount>1)) then Found:=true;
until Found=true;
{Поиск супер-чисел Смита, удолетворяющих условиям}
{Подсчет суммы цифр cупер-числа Смита}
s:=0;
numSum:=0;
numSum:=number;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SSmith:=s;
{Проверка на супер-число Смита}
SumNumb:=0;
SumSubs:=0;
numSum:=SSmith;
numSub:=SSmith;
{Подсчет суммы цифр числа}
s:=0;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SumNumb:=s;
{Подсчет суммы множителей числа}
s:=0;
factor:=2;
amount:=0;
repeat
if (numSub mod factor)=0 then
begin
{Подсчитываем сумму цифр числа (множителя)}
sfact:=0;
numb:=factor;
while numb<>0 do
begin
inc(sfact,numb mod 10);
numb:=numb div 10;
end;
sum:=sfact;
{Подсчитываем сумму множителей}
s:=s+sum;
inc(amount);
numSub:=numSub div factor
end
else inc(factor);
until numSub=1;
SumSubs:=s;
{Теперь еще проверим,чтобы это из корня кв. было простым числом}
if Sqr(Trunc(Sqrt(SSmith))) <> SSmith then simple:=false;
{Найденное число - это супер-число Смита?}
{Проверяем, чтобы сумма его цифр являлась числом Смита}
if ((SumNumb=SumSubs) and (amount>1) and (simple=true)) then SFound:=true;
until SFound=true;
inc(i);
end;
Smith:=number;
{ВЫВОД СУПЕР-ЧИСЛА СМИТА}
writeln('Ваше супер-число Смита: ',Smith);
readln;
End.


TarasBer
Ну или не туда вставь. Я не знаю, не я же программу писал. Тебе лучше знать, программу же ты, говоришь, писал.
Relrin
UP
volvo
Цитата
Дописал, но происходит зацикливание программки...
Следи за руками:

      {Теперь еще проверим,чтобы это из корня кв. было простым числом}

{ Твоя проверка была заменена на вот эти две строки: }
simple := true;
if Sqr(Trunc(Sqrt(number))) <> number then simple:=false;

{Найденное число - это супер-число Смита?}
{Проверяем, чтобы сумма его цифр являлась числом Смита}
if ((SumNumb=SumSubs) and (amount>1) and simple) then SFound:=true;

, ибо зачем ты SSmith проверяешь на полный квадрат - мне непонятно совершенно. Проверять надо number, и ничего другого. Причем, заметь, перед проверкой, изначально, считаем что number - полный квадрат. Если это не так, то simple будет False. У тебя этого не было сделано. (simple = true) в следующем условии я тоже заменил на просто simple, ну не надо делать лишнего.

Я надеюсь, типы всех переменных с Integer на LongInt поменял? Для этого не надо много изменять в программе, достаточно сделать самой первой строкой
Type Integer = LongInt;

Relrin
Полный код текущей программы

Var
Found,SFound : boolean; {Флаг для цикла}
simple : boolean; {Флаг, используемый при проверке на пр. число}
square : double; {Переменная,в котором хранится число из кв. корня}
number,numb : longint; {Число,с которого начинаем поиск...}
N : longint; {Наше супер-число Смита}
i,j,k : longint; {Счетчики для циклов}
Smith, SSmith : longint; {Искомое супер-число Смита}
SumNumb : longint; {Сумма цифр числа}
SumSubs : longint; {Сумма множителей}
amount : longint; {Кол-во простых множителей}
numSum,numSub : longint; {Переменные для поиска сумм}
factor,pr : longint; {Начальный делитель числа}
s,sfact,sum : longint; {Результат вычислений}

Begin
{ВВОД ЧИСЛА N}
write('Enter your number N: ');
readln(N);
{Поиск супер-числа Смита}
i:=0;
number:=1;
while i<>N do
begin
repeat
SFound:=false;
{Поиск числа Смита}
repeat
inc(number);
Found:=false;
SumNumb:=0;
SumSubs:=0;
numSum:=number;
numSub:=number;
{Подсчет суммы цифр числа}
s:=0;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SumNumb:=s;
{Подсчет суммы множителей числа}
s:=0;
factor:=2;
amount:=0;
repeat
if (numSub mod factor)=0 then
begin
{Подсчитываем сумму цифр числа (множителя)}
sfact:=0;
numb:=factor;
while numb<>0 do
begin
inc(sfact,numb mod 10);
numb:=numb div 10;
end;
sum:=sfact;
{Подсчитываем сумму множителей}
s:=s+sum;
inc(amount);
numSub:=numSub div factor
end
else inc(factor);
until numSub=1;
SumSubs:=s;
{Найденное число - это число Смита?}
{Проверяем, чтобы сумма его цифр была равна сумме простых множителей}
if ((SumNumb=SumSubs) and (amount>1)) then Found:=true;
until Found=true;
{Поиск супер-чисел Смита, удолетворяющих условиям}
{Подсчет суммы цифр cупер-числа Смита}
s:=0;
numSum:=0;
numSum:=number;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SSmith:=s;
{Проверка на супер-число Смита}
SumNumb:=0;
SumSubs:=0;
numSum:=SSmith;
numSub:=SSmith;
{Подсчет суммы цифр числа}
s:=0;
while numSum<>0 do
begin
inc(s,numSum mod 10);
numSum:=numSum div 10;
end;
SumNumb:=s;
{Подсчет суммы множителей числа}
s:=0;
factor:=2;
amount:=0;
repeat
if (numSub mod factor)=0 then
begin
{Подсчитываем сумму цифр числа (множителя)}
sfact:=0;
numb:=factor;
while numb<>0 do
begin
inc(sfact,numb mod 10);
numb:=numb div 10;
end;
sum:=sfact;
{Подсчитываем сумму множителей}
s:=s+sum;
inc(amount);
numSub:=numSub div factor
end
else inc(factor);
until numSub=1;
SumSubs:=s;
{Теперь еще проверим,чтобы это из корня кв. было простым числом}
simple:=true;
if Sqr(Trunc(Sqrt(number))) <> number then simple:=false;
{Найденное число - это супер-число Смита?}
{Проверяем, чтобы сумма его цифр являлась числом Смита}
if ((SumNumb=SumSubs) and (amount>1) and (simple=true)) then SFound:=true;
until SFound=true;
inc(i);
end;
Smith:=number;
{ВЫВОД СУПЕР-ЧИСЛА СМИТА}
writeln('Ваше супер-число Смита: ',Smith);
readln;
End.



При любой проверке сейчас выскакивает сообщение вида:
Runtime error 215 at $00401908
$00401908
$00407BD1

Добавлено через 5 мин.
Это во Фри Паскаль. А вот в Турбо Паскаль заработало! smile.gif
volvo
Цитата
При любой проверке сейчас выскакивает сообщение вида:
Runtime error 215 at $00401908
$00401908
$00407BD1
"Не верю" (С). Я программу твою правил именно с использованием FPC, так что рассказывать мне, что оно не работает и вылетает - не надо. Вот сейчас взял, скопировал полностью твой код из 22-го поста (FPC 2.4.0, если что) и запустил:

Running "f:\programs\pascal\tst.exe "
Enter your number N: 2
Ваше супер-число Смита: 121

Running "f:\programs\pascal\tst.exe "
Enter your number N: 3
Ваше супер-число Смита: 10201

Running "f:\programs\pascal\tst.exe "
Enter your number N: 4
Ваше супер-число Смита: 36481



Что я делаю не так?
Relrin
Уже все работает! Большое спасибо! good.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.