Onko kenelläkään kokemusta matemaattisten funktioiden käsittelystä Javassa? Erityisesti määrittelyjoukkojen käsittely ja poikkeustapaukset kiinnostaisivat. Javassa NaN ja äärettömyysarvot menevät try-catchien läpi ja esim. log x arvolla x = 0 on hyväksytty syöte, vaikka logaritmifunktion määrittelyjoukossa x > 0 (tässäkin tapauksessa try-catchit ympärillä). Miksi virheellisillä syötteillä saadaan tuloksia vaikka ei pitäisi, ja miten tällaisiin tilanteisiin tulisi varautua?
Noihin voi varautua helposti if-lauseilla. Jos (x <= 0), heität virheen, muuten lasket logaritmin.
Metabolix kirjoitti:
Noihin voi varautua helposti if-lauseilla. Jos (x <= 0), heität virheen, muuten lasket logaritmin.
Tarkoituksena ohjelmassani olisi, että käyttäjä voisi itse määrätä laskettavan funktion. Tällöin jokaiseen mahdolliseen poikkeukseen on mahdotonta itse keksiä riittävää määrää ehtoja, jotta ohjelma toimisi kaikilla syötteillä. Onko todellakin niin, että Javassa ovat matemaattisten funktioiden määritelmät päin mäkeä? Logaritmifunktio on vain yksi esimerkki.
Mitä minä olen käyttänyt, niin Javassa matemaattiset funktiot toimivat paremmin kuin monessa muussa kielessä.
0/0 -> NaN (Not a Number)
1/0 -> Infinity (ääretön)
-1/0 -> -Infinity (-ääretön)
500-1/0 -> -Infinity
1/0-500 -> Infinity
1/0-1/0 -> NaN
Toisin sanoen Java kertoo mitä lukua lähestytään, kun monet muut kielet heittää herjoja. Jos haluaa pysyä reaaliluvuissa, voi vertailla lukuja.
double nro; // laskutoimituksia // käsittelyt if((nro==Double.POSITIVE_INFINITY)|| (nro==Double.NEGATIVE_INFINITY)|| (nro==Double.NaN)) { // tähän heitetään herjaa }
Entä esimerkiksi tapaus Math.pow(Math.E, Math.log(5-x)/3) arvolla x = 5? Funktion ei pitäisi toimia tällä arvolla, mutta antaa kuitenkin arvoksi 0. Tämä on väärin. Tällaiseen tapaukseen ei voi oikein noilla iffeilläkään vaikuttaa. Ja jokaista mahdollista valmista matemaattista funktiota on mahdotonta alkaa tutkimaan.
Teet esim. näin:
public double pow(double a, double b) { ...tarkistuksia jne... return Math.pow(a, b); }
kaikille funktioille mitä tarvitset ohjelmassa.
Jappe kirjoitti:
Entä esimerkiksi tapaus Math.pow(Math.E, Math.log(5-x)/3) arvolla x = 5? Funktion ei pitäisi toimia tällä arvolla, mutta antaa kuitenkin arvoksi 0.
Logiikka, miten java sen laski:
(5-x)/3->0
log(0)->-ääretön
e potenssiin -ääretön -> 0
Valitettavasti matikkapää ei nyt toimi, eikä ole funktionpiirto-ohjelmia (eikä graafista laskinta), että voisin tarkistaa lähestyykö e^ln((5-x)/3) nollaa, kun x lähestyy 5:sta, mutta voinet tarkistaa.
Jos javan laskentatapa ei miellytä, joudut käyttämään msdos464:n tapaista tarkistusta.
Kannattaa kuitenkin heittää (throw) poikkeus, kun syöte ei miellytä.
Juu, kyllä se noin menee. Mutta tuntuu aika turhauttavalta, kun homma ei toimi luotettavasti. Nyt on ihan pakko käyttää tässä tapauksessa javaa, muuten en käyttäisikään. Ja jatkoa ajatellen taidan määritellä omat funktiot, kuten tuossa msdos464 ehdotti. Sekin vaan turhauttaa, että pitää tehdä tuo kun alkuperäisiin ei voi luottaa. Kun esim log 0:aa ei ole olemassakaan, ja se on tosiasia vaikka voissa paistaisi. Jos siis käyttäjä päättää syöttää oman funktion, jossa on useita matemaattisia funktioita ja jokainen lähestyy jotain arvoa, saadaan vastaukseksi täysin virheellisiä arvoja.
Tässä mun vinkki, miten saattaa kannattaa toteuttaa omat funktiot.
Toki kannattaa luoda NotaReal (pääluokaksi),NaNException, InfinityException ja NegativeInfinityException, vaikka lyhyyden takia esittelen niiden pääluokalla l. Exception-luokalla.
public static double pow(double a, double b) throws Exception { if((a==Double.POSITIVE_INFINITY)|| (a==Double.NEGATIVE_INFINITY)|| (a==Double.NaN)) { throw(new Exception()); } if((b==Double.POSITIVE_INFINITY)|| (b==Double.NEGATIVE_INFINITY)|| (b==Double.NaN)) { throw(new Exception()); } a=Math.pow(a,b); if((a==Double.POSITIVE_INFINITY)|| (a==Double.NEGATIVE_INFINITY)|| (a==Double.NaN)) { throw(new Exception()); } return a; }
Aihe on jo aika vanha, joten et voi enää vastata siihen.