Kirjautuminen

Haku

Tehtävät

Kilpailu

Ohjelmoi tekoäly!
Aikaa on 6.1. saakka.

Koodivinkit: PHP: Roomalaiset numerot

Kirjoittaja: GeoHound

Kirjoitettu: 09.04.2003 – 09.04.2003

Tämä ulostaa kokonaisluvut roomalaisiksi numeroiksi. Toimii vain kokonaisluvuilla (ei negatiivisiä lukuja).

<?php
# Tehnyt KeoKeo (aka. GeoHound), http://keokeo.daug.net

function rome_num($luku)
{
    settype($luku, "integer");
    if($luku <= 0) { exit("luku ei saa olla negatiivinen luku!"); }
    $tuhannet = floor($luku / 1000);
    $tuhannet2 = floor($luku / 1000);
    for ($tuhannet < 0; $tuhannet--;) { echo "M"; }
    $sadat = floor($luku / 100);
    $sadat2 = floor($luku / 100);
    $sadat = $sadat - ($tuhannet2 * 10);
    if ($sadat >= 9) { echo "CM"; $sadat-=9; }
    if ($sadat >= 5) { echo "D"; $sadat-=5; }
    if ($sadat >= 4) { echo "CD"; $sadat-=4; }
    for ($sadat < 0; $sadat--;) { echo "C"; }
    $kymmenet = floor($luku / 10);
    $kymmenet2 = floor($luku / 10);
    $kymmenet = $kymmenet - ($sadat2 * 10);
    if ($kymmenet >= 9) { echo "XC"; $kymmenet-=9; }
    if ($kymmenet >= 5) { echo "L"; $kymmenet-=5; }
    if ($kymmenet >= 4) { echo "XL"; $kymmenet-=4; }
    for ($kymmenet < 0; $kymmenet--;) { echo "X"; }
    $ykköset = $luku - ($kymmenet2 * 10);
    if ($ykköset >= 9) { echo "IX"; $ykköset-=9; }
    if ($ykköset >= 5) { echo "V"; $ykköset-=5; }
    if ($ykköset >= 4) { echo "IV"; $ykköset-=4; }
    for ($ykköset < 0; $ykköset--;) { echo "I"; }
}
?>

Kommentit

Sami [10.04.2003 15:16:46]

Lainaa #

En kokeillut mutta vaikuttaa ideana oudolta (kuka tarvitsee). Eiköhän tästä silti opi jotain (ainakin aloittelijat, esim. minä...) ja tyhmät ideathan ovat yleensä juuri hauskimpia.

snakari [10.04.2003 16:18:40]

Lainaa #

no ei tää mun mielestä tyhmä idea oo.. ei kyllä hyödyllinenkään, mutta kyllähän tästäkin jotain oppii

GeoHound [10.04.2003 16:28:01]

Lainaa #

aíniin ja voi tesmiä osoitteessa http://www.waakku.net/rome.php

Sami [10.04.2003 16:47:12]

Lainaa #

Onko 999 roomalaisilla varmasti CMXCIX ja 99 on sen mukaan XCIX? Järkevämpi se ainakin olisi, jos se olisi IM, mutta en ole täysin varma oikeellisuudesta
Entä esim. 39? Onko se XXXIX (ohjelman mukaan) vai XIL (näin luulisin sen olevan)

GeoHound [10.04.2003 18:02:32]

Lainaa #

Ainakin oppaan mukaan sanotaan että "Roomalaiset numerot eivät nykyään esiinny yhteyksissä, joissa niillä pitäisi suorittaa laskutoimituksia.". Eli toisinsanoen tommosia laskuja ei kai tehdä enään. Tosin en ole itsekkään ihan varma. Jos joku kertoisi onko tuo oikein/väärin voisin korjata asian.

GeoHound [10.04.2003 18:04:16]

Lainaa #

Niin oppaassa oli tämmösiä esimerkkejä vaan, ei "IM":ää "IV = 4, IX = 9, XL = 40, XC = 90, CD = 400 ja CM = 900".

juhotan [04.05.2003 21:02:00]

Lainaa #

Ei tos tapahu mitää!

GeoHound [20.05.2003 16:03:54]

Lainaa #

sä et osaa

odys [23.06.2003 15:09:45]

Lainaa #

Ihan kiva :)

hejppa [10.06.2007 01:07:34]

Lainaa #

kääntyyks tää beisic kääntäjäl??!

janijohannes [30.04.2009 16:59:46]

Lainaa #

Sami kirjoitti:

Onko 999 roomalaisilla varmasti CMXCIX ja 99 on sen mukaan XCIX? Järkevämpi se ainakin olisi, jos se olisi IM, mutta en ole täysin varma oikeellisuudesta
Entä esim. 39? Onko se XXXIX (ohjelman mukaan) vai XIL (näin luulisin sen olevan)

Ajatellaanpa:

1. CMXCIX:
    Parseroituna:
        CM = 1000(M)-100(C)=900 +
        XC = 100(C)-10(X)=90 +
        IX = 10(X)-1(I)=9 = 999
   IM:
    Parseroituna:
        IM = **** (Virhe: sadat, kymmenet ja ykköset määrittelemättä)
2. XXXIX:
    Parseroituna:
        XXX = 10(X)+10(X)+10(X)=30 +
        IX = 10(X)-1(I)=9 = 39
   XIL:
    Parseroituna:
        X = 10(X) +
        IL = 50(L)-1(I)=4 = 49

Selvenikö?

Grez [28.08.2019 16:34:41]

Lainaa #

Jälleen kommentoin ikivanhaan "nosto" ketjuun...

Sami kirjoitti:

Onko 999 roomalaisilla varmasti CMXCIX ja 99 on sen mukaan XCIX? Järkevämpi se ainakin olisi, jos se olisi IM, mutta en ole täysin varma oikeellisuudesta
Entä esim. 39? Onko se XXXIX (ohjelman mukaan) vai XIL (näin luulisin sen olevan)

Tässä täytyy ottaa huomioon roomalaisten numeroiden "kielioppisääntöjä"...

I toimii vähentimenä ainoastaan kirjaimille V ja X.
X toimii vähentimenä ainoastaan kirjaimille L ja C.
C toimii vähentimenä ainoastaan kirjaimille D ja M.

Mitä itse ohjelmaan tulee niin itse koodaisin sen mieluummin jotenkin näin:

<?php
function rome_num($luku)
{
	$luku = (int)$luku;
	$merkit = "MDCLXVI";
	$tulos = str_repeat($merkit[0], $luku / 1000);
	for ($i = 0, $d = 100; $i<6; $i += 2, $d/=10)
	{
		$p = ($luku / $d) % 10;
		if ($p%5==4) { $tulos .= $merkit[$i + 2]; $p++; }
		if ($p == 10) { $tulos .= $merkit[$i]; continue; }
		if ($p >= 5) { $tulos .= $merkit[$i + 1]; $p -= 5; }
		$tulos .= str_repeat($merkit[$i + 2], $p);
	}
	return $tulos;
}

Tämän tavan hyöty tietysti olisi suurempi, jos merkit jatkuisivat isompaan kuin tuhanteen.

The Alchemist [29.08.2019 06:24:31]

Lainaa #

Onkohan tuo koodi copy-pastettu monesta eri lähteestä, kun koodaustyyli vaihtelee riveittäin ja jopa for-operaattorin argumenttien sisällä...

Grez [29.08.2019 10:13:18]

Lainaa #

Ilmeisesti viittaat tuohon minun koodiini kun siellä on eroa välilyönneissä..

Koodailen yleensä muulla kielellä kehitysympäristössä, joka automaattisesti yhtenäistää sisennykset ja välilyönnit yms. Koska yleensä en koodaile PHP:llä niin rustasin tuon perus tekstieditorilla. Siinä ei tosiaan ole mitään muuta copy&pastettua kuin tuo alkuperäisen koodivinkin funktiomäärittely, että se olisi "drop in replacement". Näköjään tosin erehdyin siinä koska tuo alkuperäinenhän tuuppaa tavaran pihalle echona funktion sisältä :(

Sen verran googletin että millä funktiolla PHP:ssä saa toistettua samaa merkkiä.

Yleensäkään en copy-pasteile koodiin rivin tai parin pätkiä, koska on nopeampaa vaan kirjoittaa ne. Oikeastaan koko esimerkkini pointti on, että miten tehdä nuo toistuvat asiat ohjelmallisesti eikä kopioimalla samaa koodia pienin muokkauksin kolmeen kertaan samaan funktioon.

Tokihan tuon voisi ajaa jonkun PHP-tyylittelijän läpi, ihmisen hommana en sellaista pidä.

Alun perin itse asiassa postasin tänne koodin suoraan tekstieditorista ilman testaamista. Sitten päätin kuitenkin testata että se ylipäätään toimii ja olihan siinä virhe. Alkuperäisessä koodissa oli for -loopissa $i<6; asemesta $d; Ajattelin että $d olisi kokonaislukumuuttuja ja lopuksi menisi 0:ksi, jonka PHP tulkitsisi epätodeksi, mutta eihän nuo PHP:n muuttujat ole tyypitettyjä, joten se ilmeisesti meni 0.1:ksi jne ja looppi ei katkennutkaan.

Tässä vielä tyyliteltynä: (koneella meni 139ms)

<?php
function rome_num($luku)
{
    $luku   = (int) $luku;
    $merkit = "MDCLXVI";
    $tulos  = str_repeat($merkit[0], $luku / 1000);
    for ($i = 0, $d = 100; $i < 6; $i += 2, $d /= 10) {
        $p = ($luku / $d) % 10;
        if ($p % 5 == 4) {
            $tulos .= $merkit[$i + 2];
            $p++;
        }
        if ($p == 10) {
            $tulos .= $merkit[$i];
            continue;
        }
        if ($p >= 5) {
            $tulos .= $merkit[$i + 1];
            $p -= 5;
        }
        $tulos .= str_repeat($merkit[$i + 2], $p);
    }
    return $tulos;
}

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta