[issue9980] str(float) failure
New submission from Kiriakos Vlahos : I am the author of PyScripter a popular python IDE (pyscripter.googlecode.com). Following a user report I found out that str(float) occasionally produces wrong results with Python 2.7 and 3.1. eg. >>> str(38210.0) //wrong '3820:.0' >>> str(37210.0) // correct '37210.0' >>> str(36210.0) //wrong '3620:.0' This only happens with the embedded python engine which uses the pythonxx.dll of the official distribution. It does not happen using the stand alone interpreter of the PyScripter remote engine. The recent changes in Python 3.2a2 fix this issue. Any ideas why the embedded Python would give different results from the stand alone interpreter? -- components: Interpreter Core, Windows messages: 117574 nosy: Kiriakos.Vlahos priority: normal severity: normal status: open title: str(float) failure versions: Python 2.7, Python 3.1 ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: PyScripter is a Windows only IDE. I am using the official release *** Python 2.7 (r27:82525, Jul 4 2010, 09:01:59) [MSC v.1500 32 bit (Intel)] on win32. *** Python 3.2a2 fixes this since, according to SVN, str is now using the same code (or at least the same parameters to the _Py_dg_dtoa call) as repr. I am afraid I do not have a minimal code to reproduce this, since the error only occurs with the python.dll embedded to PyScripter. To reproduce with PyScripter you need to a) Download and install the latest version of PyScripter from pyscripter.googlecode.com b) Set the python engine to the internal (embedded python) using the menu (Run, Python Engine, Internal) c) Execute in the interpreter window str(38210.0) etc. The puzzling thing is that the same Python.dll when used by python.exe and not PyScripter produces correct results. PyScripter does not mess up with built-ins in any way or set any special flags and I see no reason why results would differ. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: Answer to Mark's question: *** Python 3.2a2 (r32a2:84522, Sep 5 2010, 22:35:34) [MSC v.1500 32 bit (Intel)] on win32. *** >>> '%.12g' % 38210.0 '3820:' So indeed the error still exists in _Py_dg_dtoa. The internal engine uses an embedded python.dll. The remote engine uses a stand-alone pythonw.exe in a separate process and communicates with it with rpyc (http://rpyc.wikidot.com/). -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: Does _Py_dg_dtoa depend on FPU flags that affect rounding or exceptions? I failed to mention that python is embedded in a Delphi executable. Delphi uses the following code at initialization. procedure _FpuInit; asm FNINIT FWAIT {$IFDEF PIC} CALLGetGOT MOV EAX,[EAX].OFFSET Default8087CW FLDCW [EAX] {$ELSE} FLDCW Default8087CW {$ENDIF} end; Default8087CW: Word = $1332;{ Default 8087 control word. FPU control register is set to this value. CAUTION: Setting this to an invalid value could cause unpredictable behavior. } -- versions: -Python 3.2 ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: Let me that add that it is impossible to fully unit test for the correctness of the str(float). I only found out by accident, because one of the users bumped into such a case. I tried to find a pattern in the misbehaved cased and it was rather difficult. Here is what I got but it is not conclusive - If the number has decimal points it prints correctly. Problems only occur with xx.0 - More specifically they only occur with x1.0 - Small numbers (less than 1) print OK. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: OK problem solved! If I set the FPU control word to $00xx I get the correct answers. Now I think that if _Py_dg_dtoa depends on specific values for the FPU control word that is bad design and likely to lead to such problems. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: If _Py_dg_dtoa requires a specific FPU control word to work correctly, it should save its state, set it to the desired state and restore it after finishing. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: Actually with control word $0032 or $3F I still do not get identical results to python.exe. PyScripter >>> '%.12g' % 38210.0 '38210.0009918' >>> str(38210.0) '38210.0009918' Python >>> '%.12g' % 38210.0 '38210' >>> str(38210.0) '38210.0' Does anybody know what is the FPU control word should be to match the results of Python? -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: Also note that different compilers initialize the FPU control word with different values. This creates a problem with embedded python that behaves differently or even produces wrong results depending on which language/compiler is used to embed it. At least this is a documentation issue. The expected value of the FPU control word should be documented. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: I found out that $x2xx (test both $12xx and $02xx) gives identical results to python. Here is what it means. The PC field (bits 9 and 8) or Precision Control determines to what precision the FPU rounds results after each arithmetic instruction in one of three ways: 00 = 24 bits (REAL4) 01 = Not used 10 = 53 bits (REAL8) <- This is required by _Py_dg_dtoa 11 = 64 bits (REAL10) (this is the initialized state) So contrary to my expectation it is not the rounding control bits but the Precision control bits that matter. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: >>For PyScripter, can you alter your Delphi layer to drop back to the >>normal >>default 53-bit precision before calling any Python stuff? Yes sure. That is how I traced the source of the problem. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: >>How about doing the check in Py_Initialize() instead? Then it will >>work for >>embedders too. It is not good practice for DLLs to change the FPU control word when loaded, because the host application may have set it to a specific value for a good reason. Delphi provides a SafeLoadLibrary function that saves the the control word and restores it after loading the DLL. If _Py_dg_dtoa can be made to work correctly independently of the value of the FPU control word that should be much better. If this means setting and restoring the control word, then this sounds like a good way forward. By the way the reason Delphi sets the precision to 64bits is that by design all floating calculations are done in 64 bit presision and then truncated back if needed. A native 10 byte floating type called Extended is also provided. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: >>How about doing the check in Py_Initialize() instead? Then it will >>work for >>embedders too. It is not good practice for DLLs to change the FPU control word when loaded, because the host application may have set it to a specific value for a good reason. Delphi provides a SafeLoadLibrary function that saves the the control word and restores it after loading the DLL. If _Py_dg_dtoa can be made to work correctly independently of the value of the FPU control word that should be much better. If this means setting and restoring the control word, then this sounds like a good way forward. By the way the reason Delphi sets the precision to 64bits is that by design all floating calculations are done in 64 bit presision and then truncated back if needed. A native 10 byte floating type called Extended is also provided. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue9980] str(float) failure
Kiriakos Vlahos added the comment: I would like to say that these are two separate issues. One is about the precision flag and the second about the exception masking flags of the FPU control words. Both issues affect a wider number of users than Python embedders using Delphi. For example C# uses 80 bit precision if I understand http://blogs.msdn.com/b/davidnotario/archive/2005/08/08/449092.aspx well. Also both issues are primarily documentation issues. If Python libraries make certain assumptions about the state of the FPU control word, these assumptions should be documented and users can then accommodate them. -- ___ Python tracker <http://bugs.python.org/issue9980> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com