Seite 1 von 2

Buffon Nadelproblem

Verfasst: Samstag 5. Juni 2010, 18:01
von bloody1337
Hallo :)

ich habe ein problem.
ich soll ein buffon`s nadelproblem-programm von pascal in python umschreiben.

das programm habe ich noch nicht verstanden.die sufu habe ich benutzt und einen topic schon dazu gefunden,
bin aber trotzdem noch nicht weitergekommen.

Bild
Bild

das ist das vorgegebene programm mit ein bisschen geschmiere...ich konnte es mir nicht verkneifen! :o

meine überlegungen bislang:

Code: Alles auswählen

import math
import random

def intp(x):
    if x>= 1.0:
        return 1
    if x<0.0:
        return -1
    return 0


t=int(input("Schusszahl eingeben:"))
s=0
i=1
while i <=t:
    x =  random.random()
    y = random.random()
    a=pi*random.random()
    b=math.cos(a)/2
    c=math.sin(a)/2
    if intp(y-b)!= intp(y+b):
        return s+1
    if intp(x-c)!= intp(x+c):
        return s+1
    
print('PI: '+str((t/s)*4))

das funktioniert bislang noch nicht.dieses problem kann ich ohne hilfe nicht lösen...
am besten wäre ein programm,welches den anweisungen aus dem pascal programm gleicht
und mit elementaren,grundlegenden befehlen arbeitet.


wäre lieb,wenn es sich jemand anschaut!


danke
grüße bloody

Re: Buffon Nadelproblem

Verfasst: Samstag 5. Juni 2010, 19:52
von BlackJack
@bloody1337: Das ist ein ziemlich grundlegendes Problem und auch ein sehr offensichtliches wenn man die Python-Grundlagen verstanden hat, und weiss welche Anweisung was bewirkt und wo sie Sinn macht. Hier bekommst Du sogar eine *sehr* eindeutige Meldung zu einem Syntaxfehler, also schonmal einen Hinweis auf etwas was so ganz sicher nicht geht: "SyntaxError: 'return' outside function"

Dann schau mal in das Pascal-Programm an der Stelle und versuche mal zu erklären warum Du das was da steht nicht fast haargenau so in Python "übersetzt", sondern ein ``return`` da hingeschrieben hast!?

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 09:10
von sma
Und wenn der offensichtliche Syntaxfehler weg ist, kann man sich ja mal überlegen, was "NameError: name 'pi' is not defined" wohl meint und dann schauen, wieso das "while" eine Endlosschleife ist.

Stefan

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 10:21
von bloody1337
huhu :)

danke für die tipps!

ich habe nun etwas verändert und mir die grundlagen noch einmal angeschaut. so sieht es bislang aus:

Code: Alles auswählen

import math
import cmath                            # mathematische Konstanten
import random

def intp(x):
    if x>= 1.0:
        return 1
    if x<0.0:
        return -1
    return 0


t=int(input("Schusszahl eingeben:"))
s=0
i=1
while i <=t:
    x = random.random()                 # zufällige Koordinaten der Nadel
    y = random.random()                 #          --""--
    a=cmath.pi*random.random()          # Winkel der Nadel von 0 bis PI
    b=math.cos(a)/2
    c=math.sin(a)/2
    if intp(y-b)!= intp(y+b):
        s=s+1
    if intp(x-c)!= intp(x+c):
        s=s+1
    i=i+1

    print('PI: '+str((t/s)*4.0))
   

die 3 genannten fehler sind behoben,aber es kommen nur unsinnige werte raus. wo liegt nun das problem?wie kann es gelöst werden? am besten die einfachste lösung!


grüße und danke
bloody

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 10:43
von philistion
Ich hab deine Implementierung mal ein wenig angepasst, du wirst sicher selbst erkennen wo der Fehler lag.

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-
import math
import random
import sys

# import psyco
# psyco.full()
# ^ Damit ginge es noch schneller

intp = lambda x: x >= 1.0 and 1 or x < 0.0 and -1 or 0
# Warum nicht auch mit einer lambda Anweisung? 
# Du kannst aber natürlich auch deine intp Funktion weiter verwenden, das war nicht das Problem.

def buffon(t):
    s = 0
    for i in xrange(t):
        x = random.random()
        y = random.random()
        a = math.pi * random.random()
        b = math.cos(a) / 2.0
        c = math.sin(a) / 2.0
        if intp(y - b) != intp(y + b):
            s = s + 1
        if intp(x - c) != intp(x + c):
            s = s + 1
    return s


# Damit man Zeitunterschiede der Implementierung messen kann,
# soll das Programm auch ein Argument annehmen koennen.
if len(sys.argv) > 1:
    t = int(sys.argv[1])
else:
    t = int(input('Schusszahl eingeben: '))

s = buffon(t)
print 'PI: ' + str(4.0 * t / s)

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 10:50
von Darii
Wenn du Python < 3 verwendest, dann bist du in die Falle der Integer-Division gelaufen. Die tritt immer auf, wenn nur ganze Zahlen an einer Division beteiligt sind. Zur Behebung entweder s vor der Division in einen float umwandeln oder lieber

Code: Alles auswählen

from __future__ import division
ganz an den Anfang schreiben, damit wird dieses Verhalten abgeschaltet.

@philistion: Woran soll bloody1337 denn das selbst erkennen? Außer das deine intp Version völlig unverständlich geworden ist, ist das einzige was wirklich einen Unterschied macht, dass du am Schluss die Multiplikation vorgezogen hast. Da gehören dann schon wirklich hellseherische Gabe dazu, ohne Vorwissen auf die Division mit ganzen Zahlen als Ursache zu schließen.

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 11:10
von philistion
Nein, ich meinte nicht das Vorziehen. Das und die Lambda Funktion war nur eine Spielerei.

Ich meinte das ".0" nach der 4 ;)

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 11:15
von Darii
philistion hat geschrieben:Ich meinte das ".0" nach der 4 ;)
Die war schon in bloody1337s Code da und macht in diesem Fall tatsächlich nur einen Unterschied, wenn die Multiplikation wie bei dir vor der Division kommt.

Worauf ich hinauswollte ist, dass bloody1337 nicht damit geholfen ist, wenn du zig-Änderungen in der Datei machst, wovon nur eine relevant(die dir anscheinend selbst nicht bewusst war) ist und ihn dann suchen lässt. Wenn man wenig Ahnung hat vermutet man die Ursache nämlich bei jeder (überflüssigen) Änderung.

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 11:20
von bloody1337
JIPPPIEEE!!!

es klappt mal was! wie auch immer... danke an philistion

und natürlich auch die anderen,die fleißig geantwortet haben :)


dann allen noch einen schönen sonnigen sonntag :>

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 11:31
von BlackJack
@philistion: Warum nicht mit einer ``lambda``-Anweisung? Weil ``lambda`` für namenslose Funktionen vorgesehen ist. Es hat keinen Vorteil gegenüber ``def`` aber den Nachteil, dass es ungewöhnlicher ist. Warum nicht *diese* ``lambda``-Anweisung? Weil "juhuu ich kenne die Randfälle der Sprache und kann alles in eine Zeile quetschen" unpythonisch ist.

@all: Ansonsten habe ich auch noch was leicht überdimensioniertes:

Code: Alles auswählen

from itertools import islice
from math import cos, pi as PI, sin
from random import random


BELOW, WITHIN, ABOVE = 'BELOW', 'WITHIN', 'ABOVE'
HORIZONTAL, VERTICAL = ORIENTATIONS = 'HORIZONTAL', 'VERTICAL'


def check_interval(x, lower=0, upper=1):
    if x < lower:
        return BELOW
    elif x >= upper:
        return ABOVE
    else:
        return WITHIN


class UnitNeedle(object):
    def __init__(self, x, y, angle):
        self.x = x
        self.y = y
        self.angle = angle
    
    @classmethod
    def random(cls):
        return cls(random(), random(), PI * random())

    def crosses_line(self, orientation):
        if orientation not in ORIENTATIONS:
            raise ValueError('orientation not in %r' % ORIENTATIONS)
        extent = (sin if orientation is HORIZONTAL else cos)(self.angle) / 2
        value = self.x if orientation is HORIZONTAL else self.y
        return check_interval(value - extent) != check_interval(value + extent)
    
    @property
    def line_cross_count(self):
        return sum(map(self.crosses_line, ORIENTATIONS))


def main():
    times = int(raw_input('times = '))
    needles = islice(iter(UnitNeedle.random, None), times)
    cross_count = sum(needle.line_cross_count for needle in needles)
    print 'PiDach =', 4.0 * times / cross_count


if __name__ == '__main__':
    main()
:-)

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 12:28
von philistion
BlackJack hat geschrieben:@philistion: Warum nicht mit einer ``lambda``-Anweisung? Weil ``lambda`` für namenslose Funktionen vorgesehen ist. Es hat keinen Vorteil gegenüber ``def`` aber den Nachteil, dass es ungewöhnlicher ist. Warum nicht *diese* ``lambda``-Anweisung? Weil "juhuu ich kenne die Randfälle der Sprache und kann alles in eine Zeile quetschen" unpythonisch ist.
Ok, die lambda-Anweisung hätte ich mir sparen können, war didaktisch nicht klug. Werde in Zukunft versuchen, an Ockhams Rasiermesser zu denken.
@all: Ansonsten habe ich auch noch was leicht überdimensioniertes:
Gibt es sowas eigentlich auf für Python? ;)

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 14:14
von BlackJack
@philistion: Ich finde ja Code-Golf interessanter. Da gibt's objektive Bewertungskriterien.

Bedingungen: Berechnung von π nach dem Algorithmus in dem Pascal-Programm, also mit `x` *und* `y`. Keine Zeile > 80 Zeichen (exclusive Newline). Das Newline am Zeilenende zählt als Zeichen. Alle Zeilen sind durch ein Newline abgeschlossen.

Eingabe vom Benutzer, kein Prompttext erforderlich, keine Fehleingaben behandeln. Ausgabe die Näherung von π.

Ich habe eine Lösung mit 180 Zeichen.

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 17:28
von b.esser-wisser
@BlackJack:
Ich komme auf 218 - die import'e reißen mich da rein :(
Aber meine intp()-Version 'gefällt' mir

Code: Alles auswählen

intp=lambda n:n>1 or-(n<0)or 0

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 17:52
von BlackJack
@b.esser-wisser: Ist ganz nett aber so lang. :-P Meine Variante ist 4 Zeichen kürzer und zwar mit der ursprünglichen Bedingung ``>=`` statt nur ``>``. Das war letztendlich so kurz, dass das Definieren einer Funktion mit ``lambda`` und zweimal Aufrufen länger ist, als den Ausdruck einfach zweimal direkt in den Code einzusetzen.

Oh, und ein Leerzeichen kannst Du noch weglassen.

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 19:45
von b.esser-wisser
215, Ich geb's erst mal auf :(
Mein Ansatz mit m(x+c,x-c) als Ersatz für "intp(x+c) != intp(x-c)" hat's nicht gebracht (abgesehen von "m=lambda a,b:any((a>=1>b,a<0,b>=1,b<0))" :twisted: ).

Btw.: Warum ist "1or 0" korrekt, aber "0or 1" ein Syntaxfehler? (Bug in python 2.6.5?)

hth, Jörg

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 20:08
von BlackJack
@b.esser-wisser: Ab Python 2.6 kann man literale Binär- und Oktalzahlen eingeben, wie das bis dato nur mit Hexadezimalzahlen ging:

Code: Alles auswählen

>>> 0x7f
127
>>> 0b01111
15
>>> 0o664
436
Bei ``0or`` denkt der Parser "Oh, ein Oktalliteral" und stolpert dann über das ``r`` was ja keine gültige Oktalziffer ist. Habe ich bisher auch noch nicht drüber nachgedacht. :-)

Re: Buffon Nadelproblem

Verfasst: Sonntag 6. Juni 2010, 20:19
von b.esser-wisser
An die 0oxx-Schreibweise hatte ich nicht gedacht, ich dachte die gäbe es erst ab python 3.x - vielleicht sollte ich mir die "what's new"-Seite mal genauer ansehen :oops:

Re: Buffon Nadelproblem

Verfasst: Montag 7. Juni 2010, 17:16
von DaMutz
ich bin bei 198 Zeichen, ich denke beim import gibt es noch Potenzial:

Code: Alles auswählen

import math as m,random as r
und natürlich bei der lambda Funktion.

Habt ihr euch auch schon gefragt was dieses Buffon Nadelproblem eigentlich bringt. Denn dieses PI Dach wird ja anhand des PI Wertes ermittelt...

Re: Buffon Nadelproblem

Verfasst: Montag 7. Juni 2010, 17:29
von BlackJack
@DaMutz: Man braucht pi ja nur weil es eine Simulation im Rechner ist. Wenn man wirklich Nadeln oder Stöcke auf Kästchenpapier oder gekachelten Boden werfen würde steckt diese Naturkonstante ja einfach in der Natur der Sache.

Re: Buffon Nadelproblem

Verfasst: Montag 7. Juni 2010, 19:27
von b.esser-wisser
Ich bin bei 203, durch den letzten Trick ist die Schleife evtl. eins zu kurz :oops:
Disclaimer: Der link ist nicht für Anfänger und erst recht nicht dazu da,irgendwas davon in einem richtigen Programm zu verwenden.