Prosta metoda dzielenia dwóch liczb

Odpowiedz Nowy wątek
2011-10-18 18:36
prezio
1
public static void main(String[] args){
        System.out.println("Iloraz: " + iloraz(4, 0)); 
        }  
    public static double iloraz(double a, double b){
        if (b!=0){
            return a/b;
        }
        else{
            System.out.println("Dzielnikiem jest zero ");
            return a/b;
        }
    }

Witam, mam mały problem, chcę zrobić metodę iloraz, która w razie gdy ktoś będzie dzielił przez 0 wyświetli stosowny komunikat. Niestety moja metoda musi zwracać wartości double, i w przypadku podanego kodu zwróci "Dzielnikiem jest zero, Iloraz: Infinity".
Czy jest jakaś możliwość zwrócenia informacji że nie wolno dzielić przez zero w obrębie tej metody, czy jest na to jakiś inny sposób?

No i widzisz co narobiłeś? ;D - Olamagato 2011-10-25 17:44

Pozostało 580 znaków

2011-10-18 19:07
0

Wyjątek.

A co ma ten wyjątek wygenerować? Bo dzielenie przez zero nie wygeneruje (chyba, że również licznik będzie zerem). - bogdans 2011-10-18 19:11
wyjątek poleci jak podzielisz int na 0, z doublami po prostu zwróci nieskończoność - Kerai 2011-10-23 13:25
Eeeee, o ile krupnicka rozumiem, to programista ma wyjątek wygenerować, zamiast nawalać po System.out. No hello... - Ranides 2011-10-23 15:54

Pozostało 580 znaków

2011-10-18 19:40
bo
0

Funkcja

        public static double iloraz(double a, double b)
        {
              return a/b;
        }

jest w Javie poprawna i zwraca zawsze wynik typu double. Możesz ją ewentualnie uzupełnić o wyświetlenie informacji, że wykonywana jest matematycznie niepoprawna operacja dzielenia przez zero.

Pozostało 580 znaków

2011-10-18 21:39
1

Możesz też sprawdzać wynik dzielenia (Double.isInfinite(wynik)) i jeśli jest niepoprawny, zamiast niego wypisywać jakąś informację.

Pozostało 580 znaków

2011-10-23 12:21
0
System.out.println("Iloraz: " + iloraz(4, 0)); 
        }  
public static double iloraz(double a, double b){
        if (b!=0){
                return a/b;
        }
        else{
                System.out.println("Dzielnikiem jest zero ");
                return -99999999.9;
        }
}

    }

Ja bym to tak rozwiązał.
Ewentualnie:

double a=4,b=0;

if (b!=0){
            System.out.println("Iloraz: " + iloraz(a, b)); 
          }  
public static double iloraz(double a, double b)
{

    return a/b;

}
edytowany 1x, ostatnio: Marcin-ZG, 2011-10-23 12:26

Pozostało 580 znaków

2011-10-23 16:31
3

Jezusie jedyny... chłop po ludzku pyta: "Czy jest jakaś możliwość ZWRÓCENIA informacji że nie wolno dzielić" - a wy nawalacie po System.out i debatujecie nad tym, jak WYKRYĆ to dzielenie...

@Marcin-ZG: za takie rzeczy w pracy morduję. Jak ktoś zwraca mi z jakiejś funkcji jakąś "magiczną wartość" która należy do dziedziny poprawnych wyników to lecą kurwy, chuje, a na koniec idę zapalić. Jak już tak robisz, to przynajmniej napisz, jak to się po ludzku robi! To znaczy: zwracając magic-number obowiązkowo javadoc'ujesz funkcję.

Przekazywanie takich błędów możesz zrealizować na 3 sposoby, od najlepszego, do najgorszego (wg mojego uznania). Opcja pierwsza: Robisz własny wyjątek, checked wyjątek - każdy musi się z nim liczyć i przechwytywać. Nie sposób nie zauważyć, że funkcja może wyrzucić błędem - nawet od razu w deklaracji widać mniej więcej jakiego rodzaju, a kompilator zmusi to try-catch. Sposób bezpieczny, sposób z drugiej strony: upierdliwy.

public static final class IlorazException extends Exception {

    public IlorazException(String message) {
        super(message);
    }

    public IlorazException(Throwable cause) {
        super(cause);
    }

}

public static double iloraz(double a, double b) throws IlorazException {
    if (b != 0) {
        return a / b;
    } else {
        throw new IlorazException("dzielenie przez zero nie lubieć ja");
    }
}

public static void main(String[] args) {
    try {
        System.out.println("Iloraz: " + iloraz(4, 0)); // wywołujesz w try-catch
    } catch(IlorazException cause) {
        System.out.println( cause ); // reagujesz na błąd, jeśli jakiś się pojawi
    }
}

No dobra, no to mniej upierdliwa wersja z wyjątkiem. Wyjątek typu unchecked. Niczego nie musisz deklarować, a ludź wywołujący nie musi przechwytywać. Oczywiście w dobrym tonie by było, jakby jednak przechwytywał, w try-catch'u wywołując. Ale może komuś się nie chce pisać non-stop try-catchów. Wygodniejsze więc, ale mniej bezpieczne: nieprzechwycony wyjątek wysadzi Ci w powietrze program. No dobra - Bogu dzięki, że własny wyjątek zrobiłeś, z sensownym komunikatem... więc mimo braku obsługi błędu jako tako to wygląda.

public static final class IlorazException extends RuntimeException {

    public IlorazException(String message) {
        super(message);
    }

    public IlorazException(Throwable cause) {
        super(cause);
    }
}

public static double iloraz(double a, double b) {
    if (b != 0) {
        return a / b;
    } else {
        throw new IlorazException("dzielenie przez zero nie lubieć ja");
    }
}

public static void main(String[] args) {
    System.out.println("Iloraz: " + iloraz(4, 0));
}

Opcja trzecia, jeśli ktoś naaaprawdę nienawidzi wyjątków, i MUSI z sobie tylko znanych przyczyn sygnalizować błąd za pomocą return... to niech [email protected]!@[email protected]! z jakimiś magicznymi liczbami, tylko zwraca coś, co od razu można rozpoznać jako wynik z dupy wzięty. Co na pewno jest wynikiem idiotycznym? Natychmiast każdy zauważy? null. Tylko, że null to z obiektami można używać, a nie z typami prostymi... no to funkcja do przeróbki musi pójść odrobinę - trzeba double zamienić na Double.

/**
 * Dzieli liczby
 * @param a dzielna
 * @param b dzielnik
 * @return iloraz albo {@code null} jeśli operacja niedozwolona
 */
public static Double iloraz(double a, double b) {
    if (b != 0) {
        return a / b;
    } else {
        return null;
    }
}

public static void main(String[] args) {
    Double result = iloraz(4, 0);
    if(result != null) {
        System.out.println("Iloraz: " + iloraz(4, 0));
    } else {
        System.out.println("ojejku");
    }
}

Ta trzecia opcja to najgorsza opcja, w 99% przypadków będziesz zapominał porównać z nullem i poleci NullPointerException - najpopularniejszy błąd w źle napisanych programach. Nawet nie myśl o pisaniu takich funkcji bez javadoc. Możesz olewać javadoc z góry na dół, możesz dawać idiotyczne nazwy funkcji, wszystko możesz pomijać, bo "nie ma czasu"/"nie chce mi się"/"zrobię jutro" - ale takie funkcje opisuj natychmiast. Opcja najgorsza, ale czasem ta opcja ma chyba sens, tak przypuszczam przynajmniej. Np ja tej opcji używałem w grupie kilkunastu funkcji, które miały coś sprawdzić, i zwrócić true/false. Dość szybko się okazywało, że funkcje muszą zwracać trzy wartości:

  • tak tak, włączono
  • nie włączono tego o co pytasz
  • eeee, ni chuja pojęcia nie mam, znaczy: nieokreślone

I szczerze mówiąc do takiej logiki trójwartościowej wolałem właśnie używać Boolean i zwracać true/false/null zamiast true/false/rzucenie wyjątku. Uznałem, że definiowanie własnego enuma akurat tutaj też jeszcze mi nie jest potrzebne, bo język całkiem nieźle i intuicyjnie trójwartościowość realizuje.

edytowany 2x, ostatnio: Ranides, 2011-10-23 16:33
Bo tylko ty uznałeś, że rzucanie w tym kodzie wyjątkami ma jakiś sens. - iooi 2011-10-23 19:48

Pozostało 580 znaków

2011-10-23 20:50
4

Bo tylko ty uznałeś, że rzucanie w tym kodzie wyjątkami ma jakiś sens. - iooi 56 minut temu

tak debilu - bo nie można sygnalizować błędu za pomocą zwracania wyniku jeśli KAŻDA wartość przyjmowana przez zmienną zwracaną może być wynikiem poprawnej operacji.

tak debilu - bo błędy obsługujesz throwami i catchami, a kontrolę przepływu if'ami i returnami. Nie na odwrót.

Jak masz ochotę się z chujem na głowy zamieniać albo nogami pisać - twój problem. Ale wyraźnie i za każdym razem będę powtarzał: zły kod to zły kod, a sranie pod siebie to sranie pod siebie.

Można też sprawę ująć inaczej: uznałem tak właśnie, bo o to facet pyta właśnie: jak sygnalizować kurwa błąd. A nie jak odróżniać czy złe dzielenie zaszło, bo to żadna filozofia przed dzieleniem porównanie z zerem porównać. Co zresztą facet zrobił w poście otwierającym pytanie.

Błędów się nie sygnalizuje napierdalając po konsoli, bo 99% twoich programów, szczególnie w Javie, konsolowa nie będzie. Zresztą takie "sygnalizowanie" to w dupę sobie można wsadzić bo konsola znika razem z procesem - od tego masz javowskie Logger, albo inne log4j, jeśli już coś trace'ować chcesz.

Ekhm, abstrahując od merytorycznie bardzo dobrych postów, z boku przy grupa jest dopisek "moderatorzy". A to do czegoś zobowiązuje. Np. nie łamania regulaminu bez względu na to jak katastrofalnie złe są posty niektórych forumowiczów. - Olamagato 2011-10-23 21:12
A co ja robię w grupie moderatorzy to nie pytaj - ja tu zajrzałem pierwszy raz od... chyba z pół roku :P - Ranides 2011-10-23 21:18
Cóż. Muszę się zgodzić z Olamagato. Moderator czy nie, kultura powinna być zachowana. - Marooned 2011-10-26 00:24

Pozostało 580 znaków

2011-10-23 21:04
0

Tak debilu, ale dzielenie przez zero dla doubli jest well-defined. Nigdzie nie pisałem nic o konsoli, debilu.
To żadna filozofia zasygnalizować błąd, bo to żadna filozofia rzucić wyjątkiem (to przecież oczywiste).

edytowany 2x, ostatnio: iooi, 2011-10-23 21:07
Może już wystarczy nawalania "debilami"? W końcu to forum jest do pomagania. Nawet pomagającym. ;) - Olamagato 2011-10-23 21:17
Oj tam, Ranides chyba tak lubi. - iooi 2011-10-23 21:20

Pozostało 580 znaków

2011-10-23 21:42
3

Przepiszę jeszcze raz pierwsze pytanie z wątku: Czy jest jakaś możliwość zwrócenia informacji że nie wolno dzielić przez zero.
Nie wykrycia, nie sprawdzenia - bo to już gość zrobił. Tylko ZWRÓCENIA INFORMACJI. Z naciskiem na informację.

iooi napisał(a)

Nigdzie nie pisałem nic o konsoli

iooi napisał(a)

i jeśli jest niepoprawny, zamiast niego wypisywać jakąś informację.

Albo nie wiesz co piszesz, albo masz słabą pamięć, albo kłamiesz. A koniec końców meritum jest takie, że ta rada jest ZŁA.

Po wykryciu nieprawidłowego zdarzenia w programie podejmujesz ZAWSZE inne działania niż wypisywanie. Uogólniając: albo naprawiasz nieprawidłowy stan, albo - jeśli nie wiesz jak to zrobić - a funkcja dzieląca z pewnością nie ma o tym pojęcia - propagujesz informację (jezu, chłopak już zadając pytanie sam zdefiniował kluczową cześć odpowiedzi!) o błędzie wewnątrz PROGRAMU, w górę, aż w końcu dotrze to do takiego miejsca, które już będzie wiedziało, co z tym fantem zrobić.

Szczególnie wszelkiego rodzaju błędy "logiki biznesowej" muszą być propagowane za pomocą mechanizmu, który niesie znaczenie dla maszyny, dla programu, dla kodu. Bo to kod działa i to kod jest analizowany. "return coś" niesie programowi prostą informację: funkcja wykonała return, znaczy zakończyła się poprawnie, znaczy wszystko jest cudownie. Żaden debugger, narzędzie profilujące, narzędzia kontroli jakości kodu nic z tej konstrukcji nie wyłapią. Stwierdzą, że jest super...

A super nie jest, bo dzielenie przez zero jest well-defined z technicznego punktu widzenia. A ta funkcja nie ma rozwiązywać problemu tranzystorów, tylko problem matematyczny. Czyli zewnętrzna komunikacja: typy argumentów, typy wyników i dozwolone operacje masz czerpać z dziedziny problemu a nie z dziedziny implementacji. Co mnie obchodzi, że standard IEEE pozwala na takie akcje? Co mnie obchodzi, że funkcja w ogóle wewnętrznie posługuje się jakimś standardem IEEE do reprezentacji liczb? Mnie obchodzi, że każdy matematyk zawału dostanie na widok 10/0 = INFINITY. My na liczbach do jasnej anielki pracujemy? Czy też może właśnie napisaliśmy super-duper hybrydową funkcję, która niby pracuje na liczbach, ale czasem to zachowuje się tak, jakby sobie traktowała to jako ciągi nieskończone i używając w dodatku niezłego skrótu myślowego zwracała wynik, który również jest niezłym skrótem myślowym.

O mój przyjacielu - słowo "dópa" do bazy danych też mogę wpisać, kodowanie UTF8 mi na to pozwoli. Ale jaknapiszę tezaurus nawalający takimi kwiatkami, to każdy normalny użytkownik stwierdzi, że program daje zwyczajnie błędne wyniki, żeby nie powiedzieć karygodne, bo wprowadzające w błąd (zupełnie jak twoja funkcja zwracająca infinity!). I nikogo nie będzie interesować, że SQL-owe INSERT jest well-defined dla ciągów "dópa".

Wypisanie, a raczej LOGOWANIE informacji do DZIENNIKA to tylko działanie dodatkowe. Wyświetlanie komunikatu użytkownikowi programu zaś to zdecydowanie zadanie dla zupełnie innej części programu niż funkcja matematyczna, która nie ma pojęcia w jakim kontekście została wywołana i w jaki sposób prowadzony jest dialog z userem. I czy w ogóle jakiś dialog jest prowadzony.

edytowany 2x, ostatnio: Ranides, 2011-10-23 21:44

Pozostało 580 znaków

2011-10-23 22:06
1
Ranides napisał(a)
iooi napisał(a)

Nigdzie nie pisałem nic o konsoli

iooi napisał(a)

i jeśli jest niepoprawny, zamiast niego wypisywać jakąś informację.

Albo nie wiesz co piszesz, albo masz słabą pamięć, albo kłamiesz. A koniec końców meritum jest takie, że ta rada jest ZŁA.
Nadal jestem pewien, że nie pisałem tu nic o konsoli. Wypisywać można logując, jeśli tak bardzo to kochasz.

Ranides napisał(a)

Po wykryciu nieprawidłowego zdarzenia w programie podejmujesz ZAWSZE inne działania niż wypisywanie. Uogólniając: albo naprawiasz nieprawidłowy stan, albo - jeśli nie wiesz jak to zrobić - a funkcja dzieląca z pewnością nie ma o tym pojęcia - propagujesz informację (jezu, chłopak już zadając pytanie sam zdefiniował kluczową cześć odpowiedzi!) o błędzie wewnątrz PROGRAMU, w górę, aż w końcu dotrze to do takiego miejsca, które już będzie wiedziało, co z tym fantem zrobić.
Szczególnie wszelkiego rodzaju błędy "logiki biznesowej" muszą być propagowane za pomocą mechanizmu, który niesie znaczenie dla maszyny, dla programu, dla kodu.
Pierdzielisz o logice biznesowej i logowaniu, a przecież od razu widać, że autor pisze program konsolowy. Mi np. grep nigdy żadnym wyjątkiem nie wypierdolił.

Ranides napisał(a)

Mnie obchodzi, że każdy matematyk zawału dostanie na widok 10/0 = INFINITY. My na liczbach do jasnej anielki pracujemy? Czy też może właśnie napisaliśmy super-duper hybrydową funkcję, która niby pracuje na liczbach, ale czasem to zachowuje się tak, jakby sobie traktowała to jako ciągi nieskończone i używając w dodatku niezłego skrótu myślowego zwracała wynik, który również jest niezłym skrótem myślowym.
(...)
Wypisanie, a raczej LOGOWANIE informacji do DZIENNIKA to tylko działanie dodatkowe. Wyświetlanie komunikatu użytkownikowi programu zaś to zdecydowanie zadanie dla zupełnie innej części programu niż funkcja matematyczna, która nie ma pojęcia w jakim kontekście została wywołana i w jaki sposób prowadzony jest dialog z userem. I czy w ogóle jakiś dialog jest prowadzony.
Funkcje matematyczne nie rzucają wyjątków. Po prostu albo są, albo nie są określone na danej dziedzinie.
A dzielenie doubli w Javie jest określone na każdym doublu i zawsze jest poprawne. To wynik może być niepoprawny.

Podsumowując - napisałbyś odpowiedni kod tak (częściowo abstrahując od pytania autora):

public static final class WtfException extends Exception {
    public WtfException(String message) {
        super(message);
    }

    public WtfException(Throwable cause) {
        super(cause);
    }
}

public static Bar doSth(Foo foo) throws WtfException {
    if (foo...) {
        return...;
    } else {
        throw new WtfException("dupa");
    }
}

public static void main(String[] args) {
    try {
        System.out.println(doSth(...)); // wywołujesz w try-catch
    } catch(WtfException cause) {
        System.out.println(cause); // reagujesz na błąd, jeśli jakiś się pojawi
    }
}

Czy tak:

public static void main(String[] args) {
    if (foo...) {
        System.out.println(...);
    } else {
        System.out.println("dupa"); // reagujesz na złe dane, jeśli są złe
    }
}

?
Twoje rozwiązanie jest równie złe co nasze.

edytowany 6x, ostatnio: iooi, 2011-10-23 22:23

Pozostało 580 znaków

2011-10-23 22:44
2

Nadal jestem pewien, że nie pisałem tu nic o konsoli. Wypisywać można logując, jeśli tak bardzo to kochasz.

Nadal więc podtrzymuję tezę o debilu, zwłaszcza, że nawet debila starasz się udawać. Pocieszę Cię, nie musisz udawać. Oczywistym jest, że polecenie: "wypisz" nie dotyczyło pisania do otwartego połączenia z serwerem tylko oznaczało nawalanie na ekran.

Pierdzielisz o logice biznesowej i logowaniu, a przecież od razu widać, że autor pisze program konsolowy. Mi np. grep nigdy żadnym wyjątkiem nie wypierdolił.

To zapraszam łaskawie kiedykolwiek rzucić okiem na JAKIKOLWIEK program konsolowy, który nie jest pisany przez domorosłego łosia, tylko ma zastosowanie w kodzie produkcyjnym. Np na mavena. Tak - rzuca wyjątkami. I tak: grep też rzuca "wyjatkami". Jak nastapi błąd, to nie klepie komunikatu na EKRAN (czyli na stdout) tylko czytelny kod leci na STDERR, a kod zakończenia programu jest RÓŻNY OD ZERO. Bo nie zgadniesz - do wymiany informacji o błędach między procesem a systemem operacyjnym nie służy nawalanie po ekraniku, ani nawet pisanie na stderr, tylko zwracanie ERRORCODE. Co grep oczywiście ROBI! A przede wszystkim: jak nauczyć się srać pod siebie pisząc "małe konsolowe programiki" to tak samo będziesz srał pod siebie pisząc coś realnego. Bo pisanie kodu to nawyki - albo zawsze robisz dobrze, albo odstawiasz chałturę.

Twoje rozwiązanie jest równie złe co nasze.

Albo nie umiesz czytać, albo myśleć - albo po prostu nie rozumiesz co to jest wyjątek. Być może dlatego, że nie piszesz nic sensownego. Trudno powiedzieć. Sygnalizowanie błedów poprzez return value to lata 70-te XX wieku. Mamy trochę bardziej rozwinięte języki wysokiego poziomu, i albo pisząc w HLLu używasz konwencji wysoko-poziomowych. Albo zasuwasz do asemblera i C. Sorry - nawet C ma mechanizm sygnałów i można w nim wysoko-poziomowo oznajmiać błędy.

Twoje rozwiązanie jest do dupy, bo kontrolę błędów realizujesz za pomocą konstrukcji, które służą do kontroli przepływu. Żeby w funkcji dzielącej nie przeoczyć tego twojego magicznego return MAGIC trzeba albo przeczytać body twojej funkcji albo javadoc'a (którego pewnie nie napiszesz - czyli zostaje body funkcji - cudownie - kilka(naście) minut analizy cudzego kodu, żeby załapać, co "może się stać po wywołaniu tego potworka"). Łatwo przeoczyć, łatwo zapomnieć - NIKT, ŻADNE narzędzie nie wskaże Ci tego jako potencjalny błąd.

Tymczasem o obsłudze checked wyjątków nie da się zapomnieć. A unchecked wyjątki może i mogą zostać zapomniane, ale nie spowodują żadnego undefined behaviour. Nieprzechwycone pójdą do catch'a wyżej. W twoim przypadku tymczasem pominięcie tego ifa i kontynuacja obliczeń na "magicznej wartości" da "magiczny wynik" bóg jeden wie jaki. I cholera wie kiedy i kto wykryje błąd.

Funkcje matematyczne nie rzucają wyjątków. Po prostu albo są, albo nie są określone na danej dziedzinie.

Jasne, i pewnie dlatego w rdzeniu języka (java.lang) masz całą serię wyjątków IllegalArgumentException / ArithmeticException / NumberFormatException / itd itp

A jak już chcesz sygnalizować przez coś returnowanego, to czymś, co jest jawnie błędne. Nie INFINITY, nie 999.999, tylko czymś, co spowoduje głośny, a nie "cichy błąd" Albo null'em, na którym próba policzenia czegokolwiek wywali NPE, albo chociażby NaN'em na Boga - bo na NaN większość funkcji też ma uczulenie i pójdzie głośny błąd.

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