4

I have been using python for my assignments for past few days. I noticed one strange thing that -

  1. When I convert string to float - it gives exactly same number of digits that were in string.
  2. When I put this number in file using struct.pack() with 4 bytes floats and read it back using struct.unpack(), it gives a number not exactly same but some longer string which I expect if as per the floating point storage

    Ex. - String - 0.931973

    Float num - 0.931973

    from file - 0.931972980499 (after struct pack and unpack into 4 bytes)

So I am unable to understand how python actually stored my number previously when I read it from string.

EDIT Writing the float (I think in python 2.7 on ubuntu its other way around, d- double and f-float)

buf = struct.pack("f", float(self.dataArray[i]))
fout.write(buf)

Query -

buf = struct.pack("f", dataPoint)
dataPoint = struct.unpack("f", buf)[0] 
node = root
while(node.isBPlusNodeLeaf()) == False:
    node = node.findNextNode(dataPoint)

findNextNode -

def findNextNode(self, num):
    i = 0
    for d in self.dataArray:
        if float(num) > float(d):
            i = i + 1
            continue
        else:                
            break
    ptr = self.pointerArray[i]
    #open the node before passing on the pointer to it
    out, tptr = self.isNodeAlive(ptr)
    if out == False:
        node = BPlusNode(name = ptr)
        node.readBPlusNode(ptr)
        return node
    else:            
        return BPlusNode.allNodes[tptr]

once I reach to leaf it reads the leaf and check if the datapoint exist there.

for data in node.dataArray:
        if data == dataPoint:
            return True
    return False    

So in this case it returns unsuccessful search for datapoint - 0.931972980499 which is there although.

While following code works fine -

for data in node.dataArray:
        if round(float(data), 6) == dataPoint:
            return True
    return False    

I am not able to understand why this is happening

codeomnitrix
  • 4,179
  • 19
  • 66
  • 102
  • Probably depends on python implementation as well. – Marcin Feb 09 '15 at 04:56
  • possible duplicate of [Packing and Unpacking binary float in python](http://stackoverflow.com/questions/16165488/packing-and-unpacking-binary-float-in-python) – Nir Alfasi Feb 09 '15 at 05:15

1 Answers1

5

float in Python is actually what C programmers call double, i.e. it is 64 bits (or perhaps even wider on some platforms). So when you store it in 4 bytes (32 bits), you lose precision.

If you use the d format instead of f, you should see the results you expect:

>>> struct.unpack('d', struct.pack('d', float('0.931973')))
(0.931973,)
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • But John what actually float(str) returned wasn't actually a double value. – codeomnitrix Feb 09 '15 at 04:58
  • 2
    Your problem now seems to be that you're doing direct comparison of floating-point values. This is a cardinal sin in most languages, including Python. For what to do about it, see this question: http://stackoverflow.com/questions/5595425/what-is-the-best-way-to-compare-floats-for-almost-equality-in-python – John Zwinck Feb 09 '15 at 05:31