1

I have checked a few examples on the Python shell and they seem to spit out same numbers. But in a program where large set of numbers are supposed to be approximated, they apparently produce different results.

I am trying to write a little program that simulates movement of an object on a rectangular plane. For that, I had to write a class named "RectangularRoom" that takes in a width and a height and creates a grid:

class RectangularRoom(object):
"""
A RectangularRoom represents a rectangular region containing clean or dirty
tiles.

A room has a width and a height and contains (width * height) tiles. At any
particular time, each of these tiles is either clean or dirty.
"""
def __init__(self, width, height):
    """
    Initializes a rectangular room with the specified width and height.

    Initially, no tiles in the room have been cleaned.

    width: an integer > 0
    height: an integer > 0
    """
    self.width = width
    self.height = height
    self.room_coordinates = []
    for m in range(self.width):
        for n in range(self.height):
            self.room_coordinates.append((m,n))
    self.cleaned = []
def cleanTileAtPosition(self, pos):
    """
    Mark the tile under the position POS as cleaned.

    Assumes that POS represents a valid position inside this room.

    pos: a Position
    """
    self.cleaned.append((int(pos.getX()), int(pos.getY())))

def isTileCleaned(self, m, n):
    """
    Return True if the tile (m, n) has been cleaned.

    Assumes that (m, n) represents a valid tile inside the room.

    m: an integer
    n: an integer
    returns: True if (m, n) is cleaned, False otherwise
    """
    assert type (m)== int and type (n) == int
    return (m,n) in self.cleaned

def getNumTiles(self):
    """
    Return the total number of tiles in the room.

    returns: an integer
    """
    return self.width*self.height

def getNumCleanedTiles(self):
    """
    Return the total number of clean tiles in the room.

    returns: an integer
    """
    return len(self.cleaned)

def getRandomPosition(self):
    """ 
    Return a random position inside the room.

    returns: a Position object.
    """
    return Position (random.randrange(0 , self.width), random.randrange(0 , self.height))

def isPositionInRoom(self, pos):
    """
    Return True if pos is inside the room.

    pos: a Position object.
    returns: True if pos is in the room, False otherwise.
    """
    return (int(pos.getX()), int(pos.getY())) in self.room_coordinates

As you see I implemented it using the int() method and the random generator "random.randrange".

In the solution, the teacher has implemented this class using the math.floor() function and the random generator random.random():

class RectangularRoom(object):
"""
A RectangularRoom represents a rectangular region containing clean or dirty
tiles.

A room has a width and a height and contains (width * height) tiles. At any
particular time, each of these tiles is either clean or dirty.
"""
def __init__(self, width, height):
    """
    Initializes a rectangular room with the specified width and height.

    Initially, no tiles in the room have been cleaned.

    width: an integer > 0
    height: an integer > 0
    """
    self.width = width
    self.height = height
    self.tiles = {}
    for x in range(self.width):
        for y in range(self.height):
            self.tiles[(x, y)] = False

def cleanTileAtPosition(self, pos):
    """
    Mark the tile under the position POS as cleaned.

    Assumes that POS represents a valid position inside this room.

    pos: a Position
    """
    x = math.floor(pos.getX())
    y = math.floor(pos.getY())
    self.tiles[(x, y)] = True

def isTileCleaned(self, m, n):
    """
    Return True if the tile (m, n) has been cleaned.

    Assumes that (m, n) represents a valid tile inside the room.

    m: an integer
    n: an integer
    returns: True if (m, n) is cleaned, False otherwise
    """
    return self.tiles[(m, n)]

def getNumTiles(self):
    """
    Return the total number of tiles in the room.

    returns: an integer
    """
    return self.width * self.height

def getNumCleanedTiles(self):
    """
    Return the total number of clean tiles in the room.

    returns: an integer
    """
    return sum(self.tiles.values())

def getRandomPosition(self):
    """
    Return a random position inside the room.

    returns: a Position object.
    """
    return Position(random.random() * self.width,
                    random.random() * self.height)

def isPositionInRoom(self, pos):
    """
    Return True if pos is inside the room.

    pos: a Position object.
    returns: True if pos is in the room, False otherwise.
    """
    return ((0 <= pos.getX() < self.width)
            and (0 <= pos.getY() < self.height))

Surprisingly, these two chunks of code produce completely different results. I want to know why this happens. int() and floor() should have the same effect on a positive number and the two random functions seem to produce similar numbers.

4

4 に答える 4

5

ええと、あなたの質問に対する答えはわかりません。まったく同じものを返すのではないかと思います。ただし、出力を説明する可能性のあるソリューションには問題があると思います。

「cleanTileAtPosition」で

self.cleaned.append((int(pos.getX()), int(pos.getY())))

「getNumCleanedTiles」で

return len(self.cleaned)

このコードでは、タイルを複数回クリーニングできるようです。タイルを「True」に設定できるのは 1 回だけであるため、これは教師のコードが行うことではありません。

(ちなみに、random.randrange は整数を返すので、整数変換は何もしません!)

EDIT:また、タイプの違いは検討する価値があると思います。ただし、すべてのタイプは「int」であるため、問題にはなりません。

于 2013-04-17T22:51:34.637 に答える
2

あなたのアプローチには1つの大きな違いがあります。random.randrangeは整数を返し、int()その位置を呼び出します。あなたは整数を扱っています。一方、random.random() * somethingfloat をmath.floor返し、float も返します。あなたの先生はいつも浮き輪を扱っています。

それは少なくとも と の違いintですmath.floorが、なぜそれがまったく異なる結果をもたらすのかはわかりません。それについてもう少し具体的に教えていただけますか?

于 2013-04-17T22:49:37.767 に答える
1

次の例を検討してください。

>>> a = 1.2
>>> b = int(a)
>>> c = math.floor(a)
>>> b
1
>>> c
1.0
>>> type(c)
<type 'float'>
>>> type(a)
<type 'float'>
>>> type(b)
<type 'int'>

int() と floor() は正の整数に対して「同じこと」を行いますが、結果の型は異なります。これにより、後で行う操作に応じて、あらゆる種類の異なる相互作用が発生する可能性があります。Python は、その観点からそれを「機能させる」方法を見つけ出しますが、必ずしも望む結果が得られるとは限りません。

一般に、プログラミングであらゆる種類の数学を行うときは、使用する型に一貫性を持たせて、型キャストや昇格などの厄介なことを心配する必要がないようにする必要があります。

于 2013-04-17T22:50:50.940 に答える
0

math.floor terhe の代わりに "integers" を使用する方が良いでしょう - それでも、Python は float <-> integer 比較に十分な黒魔術を持っているので、この違いだけでも上記のコードでは問題になりません。ただし、両方のバージョンのコードには、Java または C++ の明確な「アクセント」があり、単純な Python コードよりもはるかに複雑になっています。この丸めではなく、コードの他のポイントで違いが生じる可能性があります。たとえばrandom.randint、フロートを取得して後で丸める代わりに、最初に使用してみてください。

于 2013-04-17T22:49:15.857 に答える