sprawdzanie czy liczba to palindrom

0

Mam problem z tym o to zadaniem na spoju:
http://pl.spoj.com/problems/BFN1/
Mój kod wygląda następująco:

#include <iostream>

using namespace std;

int ileliczb(int a)
{
    if(a==0)
        return 1;
    else {int ile=0;
    while(a!=0)
        {a/=10;
        ile++;}
        return ile;}}

int odwrotnoscliczby(int a)
{
    if(a<10)
        return a;
    int liczbacyfr=ileliczb(a);
    int wynik=0;
    do{   liczbacyfr-=1;
            wynik+=(a%10)*(10*liczbacyfr);
            a/=10;}while(liczbacyfr!=1);
          return wynik+=a;

    }

bool czypalindram(int a)
{
    int odwrotnosc=odwrotnoscliczby(a);
    if(odwrotnosc==a)
        return true;
    else return false;


}
int main()
{
    int ile;
    cin >> ile;
    for(int i=1;i<=ile;i++)
       {int a;
       cin >> a;
       int j=0;
       while(czypalindram(a)!=true)
        {a+=odwrotnoscliczby(a);
       j++;}
       cout << a << " " << j << endl;
}}

Wydaje mi się, że problem tkwi w ostatniej pętli, gdy podam liczbę : 26 , to nie jest palindram, 26+62=88, wychodzi palindram wszystko działa, ale gdy już podam liczbę 28, to program świruje.
Proszę o znalezienie błędu lub jeśli kod jest do bani, to o sugestie, jak się za to zabrać :)

3

Po pierwsze, poprawiłem Twoje formatowanie, które jest tragicznie nieczytelne:

#include <iostream>

using namespace std;

int ileliczb(int a)
{
    if (a == 0)
        return 1;
    else
    {
        int ile = 0;
        while (a != 0)
        {
            a /= 10;
            ile++;
        }
        return ile;
    }
}

int odwrotnoscliczby(int a)
{
    if (a < 10)
        return a;
    int liczbacyfr = ileliczb(a);
    int wynik = 0;
    do
    {
        liczbacyfr -= 1;
        wynik += (a % 10) * (10 * liczbacyfr);
        a /= 10;
    } while (liczbacyfr != 1);
    return wynik += a;
}

bool czypalindram(int a)
{
    int odwrotnosc = odwrotnoscliczby(a);
    if (odwrotnosc == a)
        return true;
    else
        return false;
}
int main()
{
    int ile;
    cin >> ile;
    for (int i = 1; i <= ile; i++)
    {
        int a;
        cin >> a;
        int ile = 0;
        while (czypalindram(a) == true)
        {
            a += odwrotnoscliczby(a);
            ile++;
        }
        cout << a << " " << ile << endl;
    }
}

Jeśli sprawia Ci to problem to pozwól Twojemu IDE Ci pomóc, lub skorzystaj z http://format.krzaq.cc


Teraz do rzeczy:

bool czypalindram(int a)

poprawna pisownia to palindrom


int odwrotnoscliczby(int a)
{
    if (a < 10)
        return a;
    int liczbacyfr = ileliczb(a);
    int wynik = 0;
    do
    {
        liczbacyfr -= 1;
        wynik += (a % 10) * (10 * liczbacyfr);
        a /= 10;
    } while (liczbacyfr != 1);
    return wynik += a;
}

(10 * liczbacyfr) dla setek mnożysz przez 20 zamiast przez 100. Polecam std::pow z <cmath>


while (czypalindram(a) == true)

No chyba odwrotnie.


Ponadto:

  • wymyślasz koło na nowo
  • korzystasz z polskich nazw zmiennych. Lepiej przyzwyczaj się do poprawnego, angielskiego nazewnictwa
  • funkcję poniżej
bool czypalindram(int a)
{
    int odwrotnosc = odwrotnoscliczby(a);
    if (odwrotnosc == a)
        return true;
    else
        return false;
}

można zapisać znacznie krócej i czytelniej:

bool czypalindram(int a)
{
    return a == odwrotnoscliczby(a);
}
  • w sumie odwrotność liczby to termin matematyczny o innym znaczeniu
  • stosujesz przesłanianie nazw zmiennych (ile w main()). Bardzo obniża to czytelność
0
 using System;
class MainClass
{
  public static int Odwroc(int x)
  {
    string liczba = Convert.ToString(x);
    char[] charArray = liczba.ToCharArray();
    Array.Reverse( charArray );
    string reversed = new string( charArray );
    return (Convert.ToInt32(reversed));
  }
  
  public static bool CzyPalindrom(int x)
  {
    return (x == (Odwroc(x)));
  }
  
  public static int Nastepna(int x)
  {
    return (x + Odwroc(x));
  }
  
  public static void Main (string[] args)
  {
    Console.WriteLine("Podaj Liczbe: ");
    int liczba = Convert.ToInt32(Console.ReadLine());
    int iledodawan = 0;
    
    while(!(CzyPalindrom(liczba)))
    {
      liczba = Nastepna(liczba);
      iledodawan++;
    }
    
    Console.WriteLine("Wynik to " + liczba);
    Console.WriteLine("Wykonano " + iledodawan + " dodawan");
    
  }
}
      

To w c# ale chyba zrozumiesz o co chodzi.

0
int odwrotnoscliczby(int a)
{
    if (a < 10)
        return a;
    int liczbacyfr = ileliczb(a);
    int wynik = 0;
    do
    {
        liczbacyfr -= 1;
        wynik += (a % 10) * (10 * liczbacyfr);
        a /= 10;
    } while (liczbacyfr != 1);
    return wynik += a;
}
2

Na zachętę poprawiona wersja odwrotnoscliczby:

int odwrotnoscliczby(int a)
{
	if (a < 10)
		return a;
	int liczbacyfr = ileliczb(a);
	int wynik = 0;
	do
	{
		liczbacyfr -= 1;
		wynik += (a % 10) * pow(10, liczbacyfr);
		a /= 10;
	} while (liczbacyfr != 1);
	return wynik += a;
}

http://melpon.org/wandbox/permlink/4H1icSugHIiDgGPT

0
#include <iostream>
#include <cmath>



using namespace std;

int ileliczb(int a)
{
	if (a == 0)
		return 1;
	else
	{
		int ile = 0;
		while (a != 0)
		{
			a /= 10;
			ile++;
		}
		return ile;
	}
}

int odwrotnoscliczby(int a)
{
	if (a < 10)
		return a;
	int liczbacyfr = ileliczb(a);
	int wynik = 0;
	do
	{
		liczbacyfr -= 1;
		wynik += (a % 10) * pow(10, liczbacyfr);
		a /= 10;
	} while (liczbacyfr != 1);
	return wynik += a;
}

bool czypalindram(int a)
{
	int odwrotnosc = odwrotnoscliczby(a);
	if (odwrotnosc == a)
		return true;
	else
		return false;
}

int main()
{
	int ile;
    cin >> ile;
    for (int i = 1; i <= ile; i++)
    {
        int a;
        cin >> a;
        int ile = 0;
        while (czypalindram(a) != true)
        {
            a += odwrotnoscliczby(a);
            ile++;
        }
        cout << a << " " << ile << endl;
    }
}

To jest ten kod cały, normalnie zapisałem to i wysłałem na spoja, zaakceptowało, a u mnie wywala jakieś kosmiczne niepoprawne wyniki.

0

Kod wygląda ok (pomijając sugestie z pierwszego posta). Ale raczej nie obwiniałbym środowiska. Utwórz nowy projekt, wklej tam kod i zobacz czy działa.

0

Naprawdę nie rozumiem o co chodzi, chyba to zostawiam i ide do next zadania, zacząlem sprawdzać każdą funkcję, ogolnie problem znalazłem w mojej funkcji odwrotnosc, gdy chce podac odwrotnosc liczby mniejszej od 100, pisze dobrze, a gdy ponad 100, to ta odwortnosc wychodzi jakby pomniejszona o jeden(?). Dla 121 wypisuje 120, dla 452 wypisuje 451. Mam nadzieję, że to tylko w tym programie tak mi się dzieje i że przy innych nie będę miał takich problemów. Dziwne to jest naprawdę.

0

Debugowałem program, wprowadziłem 1 oraz 121, i w linii dla a=121, liczby cyfr=2 i wynik =0: wynik += (a % 10) * pow(10, liczbacyfr); program zamiast wypluć wynik 100, wypluwa 99 !!! Nie mam pojęcie czemu.

1

Zainstalowałem Visual Studio (4 godziny :-)), uruchomiłem program i działa bezbłędnie. A ten sam program w Code Blocks mi nie działał poprawnie. Też nie wiem co z tą funkcją ** pow** w CB jest nie tak.

2

W tym zadaniu nie powinno się używać funkcji pow, operującej na double, tylko pow10 (napisane przez siebie, operującej na long int).

Jakie z tego jaja mogą wyjść, widać tutaj:
http://stackoverflow.com/questions/9704195/why-pow10-5-9-999-in-c
https://www.quora.com/Why-do-pow-function-is-not-working-for-large-range-of-value
http://stackoverflow.com/questions/35968967/strange-unsigned-long-long-int-behavior

W C++ (Builder) jest funkcja pow10, ale też operuje na double, więc raczej się nie nada.

Funkcję pow10 znajdziesz np. tutaj: https://github.com/vpiotr/decimal_for_cpp/blob/master/include/decimal.h

0

Niby tak, ale dla int typ double będzie miał zawsze dostatecznie dużą precyzję aby reprezentować wszystkie wartości (na wszystkich znanych mi architekturach). A dzięki temu unika się wymyślania koła na nowo.

1 użytkowników online, w tym zalogowanych: 0, gości: 1