Vec3 prints differently on different platforms

I have Vec3(0.000001,0,0)
On linux it prints Vec3(1e-06, 0, 0)
On windows it prints Vec3(1e-006, 0, 0)

I have a problem with this inconsistency, right now I am using a special vector print function that prints same thing on both platforms. But that is getting tedious, I would like to override how vector prints: but it does not look like I can:

from pandac.PandaModules import *
v = Vec3(.000001,0,0) 
print v #Vec3(1e-06, 0, 0)

def vec3__str__(self):
    return "Vec3(%f,%f,%f)"%(self.getX(),self.getY(),self.getZ())


print Vec3.DtoolClassDict["__str__"] # <slot wrapper '__str__' of 'libpanda.Vec3' objects>
Vec3.DtoolClassDict["__str__"] = vec3__str__
Vec3.DtoolClassDict["__repr__"] = vec3__str__
print Vec3.DtoolClassDict["__str__"] # <function vec3__str__ at 0x7f3f5c0435f0>

# i can only get my function to work if use it directly
# python still uses the old on in most cases
v = Vec3(.000001,0,0)
print str(v) # Vec3(1e-06, 0, 0)
print v.__str__() # Vec3(0.000001,0.000000,0.000000)
print repr(v) # Vec3(1e-06, 0, 0)
print v.__repr__() # Vec3(0.000001,0.000000,0.000000)

Hm, isn’t it the issue with the FPU being forced into single-precision mode on Windows?

No, i think its cased by MVC++ and GCC having slightly different default format for printing float points:

in lvecBase3_src.I

////////////////////////////////////////////////////////////////////
//     Function: LVecBase3::python_repr
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void FLOATNAME(LVecBase3)::
python_repr(ostream &out, const string &class_name) const {
  out << class_name << "(" 
      << MAYBE_ZERO(_v.v._0) << ", "
      << MAYBE_ZERO(_v.v._1) << ", "
      << MAYBE_ZERO(_v.v._2) << ")";
}

You can see it just dumps them into the out stream without a care in the world.

I have tested your suggestion, its not that:


from pandac.PandaModules import *

loadPrcFileData("", """
request-dxdisplay-information #f
""")
import direct.directbase.DirectStart



v = Vec3(.000001,0,0)
print v #Vec3(1e-06, 0, 0)

def vec3__str__(self):
    return "Vec3(%f,%f,%f)"%(self.getX(),self.getY(),self.getZ())


print Vec3.DtoolClassDict["__str__"] # <slot wrapper '__str__' of 'libpanda.Vec3' objects>
Vec3.DtoolClassDict["__str__"] = vec3__str__
Vec3.DtoolClassDict["__repr__"] = vec3__str__
print Vec3.DtoolClassDict["__str__"] # <function vec3__str__ at 0x7f3f5c0435f0>

# i can only get my function to work if use it directly
# python still uses the old on in most cases
v = Vec3(.000001,0,0)
print str(v) # Vec3(1e-06, 0, 0)
print v.__str__() # Vec3(0.000001,0.000000,0.000000)
print repr(v) # Vec3(1e-06, 0, 0)
print v.__repr__() # Vec3(0.000001,0.000000,0.000000) 

out put

DirectStart: Starting the game.
Warning: DirectNotify: category 'Interval' already exists
Known pipe types:
  wglGraphicsPipe
(all display modules loaded.)
:util(warning): Adjusting global clock's real time by 5.60552e-006 seconds.
Vec3(1e-006, 0, 0)
<slot wrapper '__str__' of 'libpanda.Vec3' objects>
<function vec3__str__ at 0x03541070>
Vec3(1e-006, 0, 0)
Vec3(0.000001,0.000000,0.000000)
Vec3(1e-006, 0, 0)
Vec3(0.000001,0.000000,0.000000)

It’s true; Vec3 (along with all of the linmath objects) relies on the underlying C++ library to format its floating-point values, and there’s no universal standard as to how many digits there should be printed for the exponent. It’s also true that it’s impossible to replace the str function on any of the Panda objects, because they’re implemented using Python’s more-efficient slot-based system, instead of the more-flexible class-based system. I guess you could subclass from Vec3(), and override str() there, but you’d have to be careful to re-cast any computed results back into your subclass type.

But, still, if you’re dealing with floating-point numbers, things are not generally guaranteed to be precisely the same in different configurations anyway (the values computed on two different computers might differ in the fifth or sixth decimal, for instance). But the value should always be functionally the same, even if it is not precisely the same output.

If you’re relying on functionally equivalent values always printing the the same way, I think you’re making a mistake. Is there a better way to solve that underlying problem, whatever it is, instead of relying on this unusual formatting requirement?

David