Кто лучше?
От: Staon Украина  
Дата: 08.06.03 19:09
Оценка: :)
Доброе время суток!
У меня такое дело – мы с братом не можем выяснить, чей код эффективней. Задача простая – дано число: 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;
 }
}
Re: Кто лучше?
От: Кирпа В.А. Украина  
Дата: 09.06.03 08:04
Оценка:
Здравствуйте, Staon, Вы писали:

S>У меня такое дело – мы с братом не можем выяснить, чей код эффективней.


S>Вариант №1:

S><...>

S>Вариант №2:

S><...>

Прежде чем посылать на суд надо исправить ошибки
Их там море ...

Например

swap(m[1], m[i-2]); // если число с одной цифры то явная запись по отрицательному индексу
// да и по индексу m[1] там не цифирка

А вообще предлагаю этот топик переименовать "Найди здесь все баги"

Удалено избыточное цитирование. -- ПК.
!0xDEAD
Re: Кто лучше?
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 09.06.03 08:12
Оценка:
Здравствуйте, Staon, Вы писали:

S>Доброе время суток!

S>У меня такое дело – мы с братом не можем выяснить, чей код эффективней. Задача простая – дано число: 1) найти сумму его цифр 2) поменять вторую и предпоследнею цифры местами.


Ээээ... Эффективней будет такой код, хотя бы из за объема :


String sNumber = In->Text.Trim();
try
 {
  StrToInt(sNumber);

   int iSumDigits = 0;

  for(int i=1;i<=sNumber.Length();i++)
    {
      iSumDigits += (sNumber[i] - '0');
    }

   if(sNumber.Length() > 3)
    {
      char ch = sNumber[2];
      sNumber[2] = sNumber[sNumber.Length()-1];
      sNumber[sNumber.Length()-1] = ch;
    } 
   
 }
 catch(...) {}


Пмсал навскидку, вроде постарался все апшашки учесть... Не компилял, AS IS...
Re: Кто лучше?
От: Vadim B  
Дата: 09.06.03 15:58
Оценка:
Здравствуйте, Staon, Вы писали:

S>У меня такое дело – мы с братом не можем выяснить, чей код эффективней.

S>Вариант №1:
S>
S>for(int j=i-1;j>=0;j--)
S>{
S> b+=m[j]*pow(10, j);
S>}
S>

S>Вариант №2:
S>
S>  c1=(x/(int)pow(10,rank-2))%10;
S>  c2=(x%(int)pow(10,2))/10;
S>  x-=c1*pow(10,rank-2);
S>  x+=c2*pow(10,rank-2);
S>

IMHO код, который в такой задаче использует (int)pow(...), эффективным считаться никак не может. Кстати, он не может считаться и правильным тоже, потому что никто не гарантирует, что (int)pow(10,8)==100000000, оно вполне может оказаться на единицу меньше.
Re[2]: Кто лучше?
От: Staon Украина  
Дата: 09.06.03 16:26
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Здравствуйте, Staon, Вы писали:


S>>Доброе время суток!

S>>У меня такое дело – мы с братом не можем выяснить, чей код эффективней. Задача простая – дано число: 1) найти сумму его цифр 2) поменять вторую и предпоследнею цифры местами.

Весь смысл в неиспользовании строк, только числа.

F>Пмсал навскидку, вроде постарался все апшашки учесть... Не компилял, AS IS...

С уважением, Стас.
Re[2]: Кто лучше?
От: Staon Украина  
Дата: 09.06.03 16:28
Оценка:
Здравствуйте, Кирпа В.А., Вы писали:

КВА>Здравствуйте, Staon, Вы писали:


S>>У меня такое дело – мы с братом не можем выяснить, чей код эффективней.


КВА>Прежде чем посылать на суд надо исправить ошибки

КВА>Их там море ...

КВА>Например


КВА>swap(m[1], m[i-2]); // если число с одной цифры то явная запись по отрицательному индексу

КВА> // да и по индексу m[1] там не цифирка

КВА>А вообще предлагаю этот топик переименовать "Найди здесь все баги"


Может быть и есть ощибки, но у меня Билдер компилурует. И на 1, 2, 3 значных числах всё ОК.
Могу выслать EXE-шник. В архиве.
С уважением, Стас.
Re[2]: Кто лучше?
От: Staon Украина  
Дата: 09.06.03 16:31
Оценка:
Здравствуйте, Vadim B, Вы писали:

VB>Здравствуйте, Staon, Вы писали:


S>>У меня такое дело – мы с братом не можем выяснить, чей код эффективней.

S>>Вариант №1:
S>>
S>>for(int j=i-1;j>=0;j--)
S>>{
S>> b+=m[j]*pow(10, j);
S>>}
S>>

S>>Вариант №2:
S>>
S>>  c1=(x/(int)pow(10,rank-2))%10;
S>>  c2=(x%(int)pow(10,2))/10;
S>>  x-=c1*pow(10,rank-2);
S>>  x+=c2*pow(10,rank-2);
S>>

VB>IMHO код, который в такой задаче использует (int)pow(...), эффективным считаться никак не может. Кстати, он не может считаться и правильным тоже, потому что никто не гарантирует, что (int)pow(10,8)==100000000, оно вполне может оказаться на единицу меньше.

Спасибо за замечание, я сам это не учёл, хотя где-то среди себя знал про такую ошибку и поэтому придлогаю заменить функцию Pow на MyPow, которая будет высчитывать результат в простом цикле и возвращать int.
Re[3]: Кто лучше?
От: WoldemaR Россия  
Дата: 09.06.03 18:16
Оценка:
Здравствуйте, Staon, Вы писали:

S>... придлогаю заменить функцию Pow на MyPow, которая будет высчитывать результат в простом цикле и возвращать int.


Тогда хотя-бы так, но только не в цикле:


    int Power(const int x, unsigned int nPower)
    {
        return  (nPower==0) ? 1 :
                (nPower==1) ? x : 
                ((nPower&1) ? x : 1) * Power(x*x, nPower>>1);
    };
Re[4]: Кто лучше?
От: Vadim B  
Дата: 09.06.03 19:44
Оценка:
Здравствуйте, 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 все равно не влезет) и простой цикл будет быстрее.
Re[3]: Кто лучше?
От: Андрей Тарасевич Беларусь  
Дата: 09.06.03 21:54
Оценка: +1
Здравствуйте, 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 неизмеримо лучше. Хотя и он крив до невозможности.
Best regards,
Андрей Тарасевич
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.