Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Laskutoimitus merkkijonosta Javalla

Sivun loppuun

Macro [11.01.2011 18:27:16]

#

Morjens taas

Harjotuksen vuoksi aattelin tehdä Javalla laskimen, ja ajattelin olevan kaikkein helpoin tapa ottaa käyttäjän syöte stringiin ja muuttaa se laskutoimutukseksi. En ole vaan löytänyt mitään funktiota vielä, joka tekisi tuon muunnoksen.

Koodivinkeissä oli jokin esimerkki tehty PHP:llä säännöllisiä lausekkeita käyttäen, mutta haen jotain toisenlaista toimintoa..

Käyttäjän syöte saa sisältää merkkejä , (desimaalipilkku), + (plus), - (miinus), % (jako) ja x (kerto).

Metabolix [11.01.2011 18:36:40]

#

Nyt en oikein ymmärrä kysymystäsi. Ajattelit tehdä laskimen ja kysyt, olisiko Javassa valmista funktiota sen tekemiseen?

Voit lukea syötettä Scanner-luokalla, kuten Javassa yleensä tehdäänkin. (Nyt tiedonhakutaidot käyttöön!) Jos laskutoimitus on yksinkertainen (1 + 2), saat laskettua sen oikein parilla if-lauseella; muuten sinun pitää jäsentää siitä sulut, laskujärjestys ym. hienoudet esimerkiksi shunting yard -algoritmilla. Hyvä harjoitus on myös keksiä tuo jäsennysalgoritmi itse joko puhtaalta pöydältä tai edes lukemalla vain ihan lyhyt kuvaus.

Hennkka [11.01.2011 18:59:57]

#

Itse olen joskus tehnyt laskujen lasku -funktion, joka käsittelee laskua tekstijonona. Ensin funktio etsii sulut ja syöttää sulkujen sisällön itselleen ja korvaa sulut funktion palautusarvolla. Sitten funktio katsoo kerto- ja jakolaskun loopissa ja korvaa toimituksen tuloksella ja tekee saman yhteen- ja vähennyslaskulle ja lopulta palauttaa tuloksen käyttäjälle.

Esim.

3*(1,4+2,3)/2
->1,4+2,3=3,7
3*3,7/2
11,1/2
5,55

(-> = sulkujen lasku)

Tiedän, että tämä ei ole kovinkaan hyvä tapa laskea laskua, mutta toimii ja voi olla aloittelijalle ihan hyvä.

Macro [11.01.2011 19:03:08]

#

Mulla tuli joku ajatusvirhe, kun kirjoitin "ottaa käyttäjän syöte stringiin". Tarkoitin kyllä jotain muuta, eikä ole tarkoitus ottaa käyttäjältä minkään näköistä tekstiä.

Se mitä tarkoitin tuolla, olisi jotenkin tälläinen. Erona vaan, että lauseketta ei pidä etsiä, vaan se pitää suorittaa stringistä.

Metabolix [11.01.2011 19:08:15]

#

Miksi se pitää suorittaa stringistä?

Joka tapauksessa tilanne on sama kuin käyttäjältä luettaessa. Voit edelleen käyttää Scanner-luokkaa syötteen parsimiseen, ja laskeminen tapahtuu edelleen aivan samalla tavalla.

Macro [12.01.2011 16:52:25]

#

Miten laskeminen tapahtuu edelleen "samalla" tavalla?

Joko ymmärsit mitä tarkoitan, ja en sitten ymmärtänyt tuota Scanner-luokkaa tai et ymmärtänyt. Javascriptissä on täsmälleen sellainen funktio jonka tarvitsen, nimittäin eval (var tulos = eval("1+2/2"), palauttaa 2).

Tutkin tuota Scanner-luokkaa, mutta en keksinyt miten sillä saataisiin tehtyä tuo.

Metabolix [12.01.2011 16:59:48]

#

Niin, tuollainen eval-funktio kuuluu tyypillisesti skriptikieliin, joissa on koko ajan alla se tulkki, joka ymmärtää tekstimuotoista syötettä. Java ei ole skriptikieli, joten siinä ei ole tuollaista funktiota; Javan virtuaalikone ei ymmärrä tekstimuotoista lähdekoodia. Sama pätee kaikenlaisiin muihinkin käännettäviin kieliin.

Sinun pitää siis itse ohjelmoimalla purkaa lauseke osiin ("1", "+", "2", "/", "2") ja itse suorittaa oikeat laskut sopivien ehtolauseiden ja apumuuttujien avulla. Mainitsemani shunting yard -algoritmi yhdessä pinolaskimen kanssa on siihen yksi helppo tapa. Hennkan esityskin on oikeastaan vain yksi tapa toteuttaa samainen algoritmi ja pinolaskin yhdistettynä siten, että lauseketta lasketaan jo purkamisen aikana ja "pino" muodostuu funktion rekursiosta.

Triton [12.01.2011 20:41:03]

#

Niin siis tuo Scanner-luokkahan on tarkoitettu nimenomaan syötteen lukemiseen käyttäjältä ainakin konsolista sekä tiedostosta tai sitten sillä pystyy tutkimaan syötettä jollain tavoin (en aivan kaikkia mahdollisuuksia tunne)...

Tossa on vielä pieni demostraatio scanner käytöstä...

import java.util.Scanner;

public class TietojenLukemista {

	public static Scanner lukija = new Scanner(System.in);
	public static void main(String[] args) {

		System.out.println("Kirjoita jotain: ");
		String syote = lukija.nextLine();
		System.out.println("Kirjoitit: " + syote);

	}


}

(Koodia ei ole testattu, mutta tod. näk. toimii)

Metabolix [12.01.2011 21:03:12]

#

Scanner-luokalla voi lukea syötettä mm. käyttäjältä, tiedostosta, socketista tai merkkijonosta, ja sillä olisi melko helppo lukea lausekkeesta lukuja ja symboleja parin säännöllisen lausekkeen avulla. Toisaalta yhtä helposti lausekkeen voi jäsentää muuten vain säännöllisillä lausekkeilla, eikä olisi kovin kummoinen vaiva myöskään lukea lauseketta merkki kerrallaan silmukassa. Valinta riippuu lähinnä omista tottumuksista ja taidoista.

Triton, turhaan alustat sen syote-muuttujan.

Triton [12.01.2011 21:09:46]

#

Metabolix kirjoitti:

Triton, turhaan alustat sen syote-muuttujan.

Joo-o. Noi on jotain jäänteitä yliopiston laskareista... :D

Edit. Onhan tuon Scanner-luokan käyttäminen huomattavasti helpompaa (tai ainakin nopeampaa), kuin lähteä filtteröimään bittivirtaa InputStreamin sekä sun muiden luokkien avulla...

_Pete_ [13.01.2011 16:28:32]

#

Käyttämällä

http://jeplite.sourceforge.net/faq.html

voi tehdä näin:

http://pastebin.com/QvGwrevb

Ajon tuloksena on:

1+2*600-100/100 = 1200.0

etsubu [19.01.2011 20:37:24]

#

HYVIN yksin kertainen laskin joka ei osaa laskea muuta: kuin plus miinus jako kerto laskut Voisi näyttää tältä:

import java.util.Scanner;

public class laskin {
	private static Scanner lukija=new Scanner(System.in);

	public static int Kerro(int luku1,int luku2){
		return luku1*luku2;
	}
	public static double Jaa(int luku1,int luku2){
		return luku1/luku2;
	}
	public static int Vahenna(int luku1,int luku2){
		return luku1-luku2;
	}
	public static int Lisaa(int luku1,int luku2){
		return luku1+luku2;
	}
	public static void main(String[] args){
		System.out.println("Syötä lasku");
		String lasku=lukija.nextLine();

		if(lasku.indexOf("*")!=-1){
			int monesko=lasku.indexOf("*");
			String luku1=lasku.substring(0,monesko);
			String luku2=lasku.substring(monesko+1,lasku.length());
			int sluku1=Integer.parseInt(luku1);
			int sluku2=Integer.parseInt(luku2);
			int vastaus=Kerro(sluku1,sluku2);
			System.out.println(sluku1+"*"+sluku2+"="+vastaus);
		}
		else if(lasku.indexOf("/")!=-1){
			int monesko=lasku.indexOf("/");
			String luku1=lasku.substring(0,monesko);
			String luku2=lasku.substring(monesko+1,lasku.length());
			int sluku1=Integer.parseInt(luku1);
			int sluku2=Integer.parseInt(luku2);
			double vastaus=Jaa(sluku1,sluku2);
			System.out.println(sluku1+"/"+sluku2+"="+vastaus);
		}
		else if(lasku.indexOf("-")!=-1){
			int monesko=lasku.indexOf("-");
			String luku1=lasku.substring(0,monesko);
			String luku2=lasku.substring(monesko+1,lasku.length());
			int sluku1=Integer.parseInt(luku1);
			int sluku2=Integer.parseInt(luku2);
			int vastaus=Vahenna(sluku1,sluku2);
			System.out.println(sluku1+"-"+sluku2+"="+vastaus);
		}
		else if(lasku.indexOf("+")!=-1){
			int monesko=lasku.indexOf("+");
			String luku1=lasku.substring(0,monesko);
			String luku2=lasku.substring(monesko+1,lasku.length());
			int sluku1=Integer.parseInt(luku1);
			int sluku2=Integer.parseInt(luku2);
			int vastaus=Lisaa(sluku1,sluku2);
			System.out.println(sluku1+"+"+sluku2+"="+vastaus);
		}
		else{
			System.out.println("Virheellinen lasku.");
		}
	}
}

Mod. lisäsi kooditagit.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta