Доброе время суток!
У меня такое дело – мы с братом не можем выяснить, чей код эффективней. Задача простая – дано число: 1) найти сумму его цифр 2) поменять вторую и предпоследнею цифры местами. Число типа int, ввод – компонент In, вывод суммы – Sum, вывод модифицированного числа – Out. Хотелось бы узнать Ваше мнение насчёт эффективности кода и его читабельности (понимания). Среда разработки – Cbuilder 4. Вариант №1:
#include <vcl.h>
#include <algorithm.h>
#pragma hdrstop
#include"main.h"#include <math.h>
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::OKClick(TObject *Sender)
{
int a, m[5], i=0, s=0;
long int b(0);
a=StrToInt(In->Text);
while (a!=0)
{
m[i]=a%10;
a/=10;
s+=m[i++];
}
swap(m[1], m[i-2]);
for(int j=i-1;j>=0;j--)
{
b+=m[j]*pow(10, j);
}
Sum->Text=IntToStr(s);
Out->Text=FloatToStr(b);
}
Вариант №2:#include <vcl.h>
#include"math.h"#pragma hdrstop
#include"main.h"#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::startBtnClick(TObject *Sender)
{
long int x;
int sum=0;
int rank=0;
x=StrToInt(In->Text);
while (x>0)
{
sum+=x%10;
x/=10;
rank++;
}
Sum->Text=IntToStr(sum);
x=StrToInt(In->Text);
if (x>9)
{
short c1, c2;
c1=(x/(int)pow(10,rank-2))%10;
c2=(x%(int)pow(10,2))/10;
x-=c1*pow(10,rank-2);
x+=c2*pow(10,rank-2);
x-=c2*10;
x+=c1*10;
Out->Text=x;
}
}
Здравствуйте, Staon, Вы писали:
S>Доброе время суток! S>У меня такое дело – мы с братом не можем выяснить, чей код эффективней. Задача простая – дано число: 1) найти сумму его цифр 2) поменять вторую и предпоследнею цифры местами.
Ээээ... Эффективней будет такой код, хотя бы из за объема :
IMHO код, который в такой задаче использует (int)pow(...), эффективным считаться никак не может. Кстати, он не может считаться и правильным тоже, потому что никто не гарантирует, что (int)pow(10,8)==100000000, оно вполне может оказаться на единицу меньше.
Здравствуйте, Flamer, Вы писали:
F>Здравствуйте, Staon, Вы писали:
S>>Доброе время суток! S>>У меня такое дело – мы с братом не можем выяснить, чей код эффективней. Задача простая – дано число: 1) найти сумму его цифр 2) поменять вторую и предпоследнею цифры местами.
Весь смысл в неиспользовании строк, только числа.
F>Пмсал навскидку, вроде постарался все апшашки учесть... Не компилял, AS IS...
С уважением, Стас.
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Здравствуйте, Staon, Вы писали:
S>>У меня такое дело – мы с братом не можем выяснить, чей код эффективней.
КВА>Прежде чем посылать на суд надо исправить ошибки КВА>Их там море ...
КВА>Например
КВА>swap(m[1], m[i-2]); // если число с одной цифры то явная запись по отрицательному индексу КВА> // да и по индексу m[1] там не цифирка
КВА>А вообще предлагаю этот топик переименовать "Найди здесь все баги"
Может быть и есть ощибки, но у меня Билдер компилурует. И на 1, 2, 3 значных числах всё ОК.
Могу выслать EXE-шник. В архиве.
С уважением, Стас.
Здравствуйте, Vadim B, Вы писали:
VB>Здравствуйте, Staon, Вы писали:
S>>У меня такое дело – мы с братом не можем выяснить, чей код эффективней. S>>Вариант №1: S>>
VB>IMHO код, который в такой задаче использует (int)pow(...), эффективным считаться никак не может. Кстати, он не может считаться и правильным тоже, потому что никто не гарантирует, что (int)pow(10,8)==100000000, оно вполне может оказаться на единицу меньше.
Спасибо за замечание, я сам это не учёл, хотя где-то среди себя знал про такую ошибку и поэтому придлогаю заменить функцию Pow на MyPow, которая будет высчитывать результат в простом цикле и возвращать int.
Здравствуйте, WoldemaR, Вы писали:
WR>Тогда хотя-бы так, но только не в цикле:
WR>
WR> int Power(const int x, unsigned int nPower)
WR> {
WR> return (nPower==0) ? 1 :
WR> (nPower==1) ? x :
WR> ((nPower&1) ? x : 1) * Power(x*x, nPower>>1);
WR> };
WR>
Это будет быстрее работать только при больших nPower (хотя бы несколько десятков). Если x==10 (как в этой программе), то nPower<=10 (больше в int все равно не влезет) и простой цикл будет быстрее.
Здравствуйте, Staon, Вы писали:
КВА>>Прежде чем посылать на суд надо исправить ошибки КВА>>Их там море ...
КВА>>Например
КВА>>swap(m[1], m[i-2]); // если число с одной цифры то явная запись по отрицательному индексу КВА>> // да и по индексу m[1] там не цифирка
КВА>>А вообще предлагаю этот топик переименовать "Найди здесь все баги"
S>Может быть и есть ощибки, но у меня Билдер компилурует. И на 1, 2, 3 значных числах всё ОК. S>Могу выслать EXE-шник. В архиве.
"Билдер компилирует" — это вообще к делу не относится. А насчет "все ОК" — значит плохо тестировали. Такая программа может "работать" только по счастливой случайности. Да и то только в хорошую погоду. Как тебе уже объяснили, при использовании однозначных чисел твой 'swap' будет доступаться к элементу массива 'm' с индекcом '-1'. Причем будет пытаться модифицировать этот элемент, что приведет если не к краху программы, то к разрушению чужой памяти.
Например, при компиляции отладочной версии этой реализации при помощи MSVC++ 6, программа выдает полную ерунду для однозначных чисел. А при компиляции релизной версии программа как-бы "работает" благодаря счастливому совпадению — этот 'swap' разрушает память, занимаемую переменной 'j', а она после этого сразу переинициализируется. Это "спасает" ситуацию. Еcли при следующей компиляции расположит перемнные чуть по другому, программа будет падать. На точно такой же случайности основана "работоспособность" твоей программы в Билдере.
С этой точки зрения вариант 2 неизмеримо лучше. Хотя и он крив до невозможности.