Ile cyfr ma liczba

Odpowiedz Nowy wątek
2013-05-01 15:55
0

Witam,
Mam napisac funkcje ktora bedzie zwracala ilość cyfr danej liczby. Doszedlem tylko do czegos takiego, ze wywali mi cyfre pierwsza.
O to moj kod

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(lol(3));
            Console.ReadLine();
        }
        static int lol(int x)
        {
            int liczba = int.Parse(Console.ReadLine());

            int kolejna_cyfra = 0;
            while (liczba > 0)
            {
                kolejna_cyfra = liczba % 10;
                liczba /= 10;
            }
            return kolejna_cyfra;

        }
    }
}

No niestety potrzebuje wszystkich cyfr podanej liczby. Ktos pomoze? Pozdrawiam

Pozostało 580 znaków

2013-05-01 16:02
3

Log10

Pozostało 580 znaków

2013-05-01 16:16
3

int liczba = 123454456;
int iloscCyfr = liczba.ToString().Length;


Pokaż pozostałe 3 komentarze
@bogdans Rzeczywiscie o tym nie pomyślałem. - Bumcykowy 2013-05-01 17:22
Mam rozumieć, że 6 jest liczba dwucyfrową, a -15 jednocyfrową? - bogdans 2013-05-01 17:37
sposób wprowadzania ze spoja: pierwsza liczba oznacza ilość testów ;) - spartanPAGE 2013-05-01 17:39
nie wiedziałem ;) - bogdans 2013-05-01 17:44

Pozostało 580 znaków

2013-05-01 16:18
5

Uzupełniając odpowiedź @Marcin.Miga:
ilosc_cyfr_w_liczbie_x = trunc(log10(abs(x))+1)
(+specjalny przypadek dla zera)


Pozostało 580 znaków

2013-05-01 16:25
0

Jeżeli koniecznie chcesz na piechotę, to realizując Twoją koncepcję, należy zliczać ilość przebiegów pętli while w metodzie lol. Kolejne cyfry otrzymujesz przy każdym przebiegu tej pętli.

edytowany 1x, ostatnio: andrzejlisek, 2013-05-01 16:26

Pozostało 580 znaków

2013-05-01 18:01
DobryKodToTestowany
0

Panowie... porażka

Jeśli podajecie odpowiedzi to podawajcie chociaż te poprawne :)
Dużo się mówi o tym, aby programiści pisali testy. Nawet na forum się o tym mówi, dlaczego więc Panowie tego nie robicie?

Może dlatego, że przyjdzie ktoś taki jak ja i Was wyręczy :)?

Przejdźmy do wyjaśnienia sprawy:
Najlepszą odpowiedzą w tym wątku było jak na razie:

ilosc_cyfr_w_liczbie_x = trunc(log10(abs(x))+1)
(+specjalny przypadek dla zera)

Z Cóż... absolutnie nie bardzo wierzę w takie "wzorki", bo zazwyczaj mają haczyki. Nie inaczej było w tym przypadku.

Napisałem taki oto kod:

       private int GetIloscCyfrWLiczbie(double x)
        {
            if (x == 0) return 1;
            return (int)Math.Truncate(Math.Log10(Math.Abs(x)) + 1);
        }

Jest to funkcja na dodatek błędna, gdyż jak autor rozwiązania podał - funkcja potrzebuje specjalnego traktowania dla wartości "0".
Dla liczby 0 wynikiem jest liczba 1.
Co jednak jeśli liczbą będzie "000"? O tym dalej...

oraz funkcję testującą:

private void Test(double x, double result)
        {
            if (GetIloscCyfrWLiczbie(x) == result)
                Console.WriteLine("OK");               
            else
                Console.WriteLine("Błąd");
        }

A następnie przypadki testowe: (w komentarzach podane wyniki testów)

Test(1, 1); // ok
Test(12, 2); // ok
Test(-1, 1); // ok
Test(-12, 2); // ok
Test(0, 1); // ok
Test(01, 2); // blad
Test(4294967296, 10); // ok
Test(-4294967296, 10); // ok
Test(111, 3); // ok
Test(-111, 3); // ok
Test(00, 2); // blad
Test(11.1, 3); // blad

Tak jak się spodziewałem. Wzór nie jest poprawny dla pewnych danych szczególnych.
Pierwszy błąd pojawia się w momencie gdy pierwszymi cyframi jest / są zera. Są one wtedy pomijane, zgodnie zresztą z tym jak powinno być. Problem w tym jednak, że w naszym przypadku nie o to nam chodzi i z tego powodu otrzymujemy błędną wartość.

W kolejnym przypadku pojawia się ten sam problem. Tutaj dodatkowo test sprawdzający unikalność cyfr (o tym potem).

Ostatni test, który nie przechodzi poprawnie to jak łatwo się było domyślić - test liczby zmiennoprzecinkowej.

Co, więc należy zrobić? Nic specjalnego. Wystarczy napisać taką oto funkcję:

private int GetIloscCyfrWLiczbie(string x)
         {
            int result = 0;
            for (int i = 0; i < x.Length; i++)
            {
                if (char.IsNumber(x[i]))
                    result++;
            }
            return result;
        }

Lekko zmodyfikowany test naszej funkcji:

private void Test(string x, double result)
        {
            if (GetIloscCyfrWLiczbie(x) == result)
                Console.WriteLine("OK");
            else
                Console.WriteLine("Błąd");
        }

oraz przypadki testowe: (w komentarzach podane wyniki)

Test("1", 1); // ok
Test("12", 2); // ok
Test("-1", 1); // ok
Test("-12", 2); // ok
Test("0", 1); // ok
Test("01", 2); // ok
Test("4294967296", 10); // ok
Test("-4294967296", 10); // ok
Test("111", 3); // ok
Test("-111", 3); // ok
Test("00", 2); // ok
Test("11.1", 3); // ok

Jak zrozumiałem zadanie dotyczy "ile jest cyfr w danej liczbie", czyli ile jest łącznie WSZYSTKICH cyfr.

Jeśli jednak źle zrozumiałem zadanie i chodzi o unikalne cyfry, czyli np w liczbie "111", występuje tylko jedna cyfra i jest nią "1",
albo w liczbie "122" występują dwie cyfry 1 i 2 to należy zmodyfikować moją funkcję na taką:

private int GetIloscCyfrWLiczbie(string x)
        {
            List<int> numbers = new List<int>();
            int result = 0;
            for (int i = 0; i < x.Length; i++)
            {
                if (char.IsNumber(x[i]))
                {
                    if (numbers.IndexOf(x.ToString()[i]) == -1)
                        result++;
                }
            }
            return result;
        }

I oto poprawne rozwiązanie problemu :)
Tak się podaje poprawne odpowiedzi panowie :)

Pokaż mi przykład, gdzie (np) int będzie zawierał "000", a nie "0". (oczywiście pomijając to co się dzieje w pamięci, gdzie każdy bit ma w takiej sytuacji 0) EDIT: no i kodzik :D http:ideone.com/lmwjG5 - spartanPAGE 2013-05-01 18:14

Pozostało 580 znaków

2013-05-01 18:13
2

gdyż jak autor rozwiązania podał - funkcja potrzebuje specjalnego traktowania dla wartości "0".

Może jestem ślepy, ale gdzie jest tak napisane?

Wzór nie jest poprawny dla pewnych danych szczególnych.

Wzór nie będzie poprawny tylko dla liczb "z przecinkiem"- wtedy należy mnożyć liczbę przez 10, dopóki występuje wartość "po przecinku".

Są one [zera] wtedy pomijane

To nie jest błąd we wzorze - po prostu w matematyce zero to zero, milion zer jest również równe zeru.
00000000000000=0
ilosc_cyfr(00000000000000)=ilosc_cyfr(0)=1


Pozostało 580 znaków

2013-05-01 18:15
1

Głupoty waść opowiadasz.
Po pierwsze, chodziło (spójrz na pierwszy post) tylko o liczby całkowite.
Po drugie, pytamy o ilość cyfr w liczbie, nie ma liczby 00034, jest liczba 34.
Inna rzecz, że rozwiązanie @Patryk27'a trunc(log10(abs(x))+1) jest poprawne matematycznie, ale niekoniecznie informatycznie. Należałoby sprawdzić jaka (w komputerze) jest wartość log10(10^k): k, trochę więcej niż k, prawie k.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell

Pozostało 580 znaków

2013-05-01 20:18
DobryKodToTestowany
0

Hmmm, ok ale ja chciałem dostosować mój problem do potrzeb ogólnych.
Teraz gdy na forum przyjdzie inny "ktosik" i będzie miał podobny problem, ale już w tym przypadku z liczbami zmiennoprzecinkowymi to Wasz sposób nie zadziała a mój tak. (fakt, że nie doczytałem, że chodziło o cyfry całkowite)

Co do 0034 i innych to faktycznie przesadziłem. Chociaż... sposób do ostry test zawsze jest :)

"cyfry całkowite"? Błagam. - Tacet 2013-05-01 22:07

Pozostało 580 znaków

2013-05-02 08:33
0

Alternatywne rozwiązanie do powyższych.

public static int LiczbaCyfr( int x )
{
    int digits = 0;

    do
        digits++;
    while((x /= 10) != 0);

    return digits;
}

EDIT: dodam jeszcze krótki komentarz dlaczego w ogóle ten post się pojawił, bo na pierwszy rzut oka wygląda jak musztarda po obiedzie. Otóż uważam za przedstawione przeze mnie rozwiązanie za:

  • krótkie (5 linijek kodu)
  • proste (żadnych odwołań do funkcji)
  • bezawaryjne (działa poprawnie dla każdego int - i to widać na pierwszy rzut oka)

Natomiast korzystając z log10 rzutujemy int -> double i już w tym momencie się zapala lampka ostrzegawcza - nie lubię reprezentacji zmiennoprzecinkowych. Korzystamy z abs(), czyli overflow dla int.MinValue. No i musimy zrobić osobny przypadek dla 0. Log10 jest na pewno lepsze jeśli idzie o wydajność.

edytowany 3x, ostatnio: Zenek1999, 2013-05-02 09:19

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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