Array printing and another question
Hi Folks, I'm pretty new to Numpy, and I hope someone can help me out with a couple newbie questions. First, I'd like, for diagnostic purposes, to print arrays of floating point numbers in a format of my choosing. Specifically, I have a formatting function that generates strings which represent all the bits of an FP number exactly, but it formats the exponent, exponent sign, and sign separately from the mantissa so I can get a rough idea of the magnitude at a glance. We use this to verify that certain operations are yielding exactly the same FP values either across platforms or across algorithmic changes. I'd like to be able to print numpy arrays in this format. At this point I've thought of three ways to try this. First, there's using set_string_function() and then writing my own version of array2string() that uses my function for FP arrays. OK, but I'd kind of like to avoid the work of duplicating the nice way that array2string() formats arrays of different ranks. Enticingly, I see code in core/arrayprint.py that's looking for an _format attribute and using it if it exists. So the second idea is to hook into this somehow, but I don't see how (indeed, I'm not sure when an array ever has an _format attribute?). Finally, I imagine I could make my own dtype so that array2string will format with %s, then convert FP arrays into arrays of that dtype for printing. Any ideas which of these would be better, or other ideas, would be most appreciated. Second, I wanted to find out how numpy developers and experts feel about crossplatform differences in FP behavior. Is this considered unavoidable and expected, a bug, or somewhere in between? Until recently I was about to get exact matches everywhere, but I now have at least one example of a difference. I should clarify that I'm not talking about processorfamily dependency; all my machines are x86 at this point. Indeed, the differences appear across virtual machines running different OSs on the same physical machine. Thanks in advance, Ken Basye kbasye1@jhu.edu
Will set_printoptions not work for you? <URL:http://www.scipy.org/Numpy_Example_List_With_Doc#headcc1302f5e9e57de71b578cf25e8a9ffd8aa3a707> hth, Alan Isaac
Hi, Thanks, but it's been my experience that formatting FP numbers into decimal causes a lot of false alarms all by itself; that is, you get different decimal representations of the same FP memory value. I've had this happen often enough that I found the first thing I did when an output difference arose was to print the FP in hex to see if the difference was "real" or just a formatting artifact. This formatting function is designed to do that all the time, while providing enough clarity to examine values. Here are a couple examples:
pi = 3.14159 float_to_readable_string(100*pi) '(+0008)0x3a28b43958106' # Note that the exponent is a decimal value with a base of 2, so "8" is 256. float_to_readable_string(0.0) '+(1023)0x0000000000000'
These strings can also be converted back to FP with absolute accuracy, which is almost impossible to guarantee with decimal representations, in my experience. Ken Alan G Isaac wrote:
Will set_printoptions not work for you? <URL:http://www.scipy.org/Numpy_Example_List_With_Doc#headcc1302f5e9e57de71b578cf25e8a9ffd8aa3a707>
hth, Alan Isaac
_______________________________________________ Numpydiscussion mailing list Numpydiscussion@scipy.org http://projects.scipy.org/mailman/listinfo/numpydiscussion
Am Dienstag, 08. April 2008 17:22:33 schrieb Ken Basye:
I've had this happen often enough that I found the first thing I did when an output difference arose was to print the FP in hex to see if the difference was "real" or just a formatting artifact.
Nice idea  is that code available somewhere / could you post it? As a side note, there is a second big source of buglike experiences with the x86 architecture: floating point values are represented with a higher precision inside the FPU (e.g. 80 bits instead of 64), but that probably only matters for compiled programs where the compiler may (or may not) optimize intermediate, truncating FPU>memory operations away (which leads to differing results and is one of the most often reported "bugs" of the GCC optimizer).  Ciao, / / // / / ANS
Hi, Thanks for the reply. The formatting code, such as it is, is below. It uses Martin Jansche's double.py (http://symptotic.com/mj/double/double.py) and then does some simple bit twiddling. I'm still hoping someone can help me find a way to use this format for arrays of float64s. Ken ================================ import double as _double def float_to_readable_string(f): ftype = _double.fpclassify(f) assert ftype == 'NORMAL' or ftype == 'ZERO' bits = _double.doubleToRawLongBits(f) exponent = (bits >> 52) & 0x7ff mantissa = bits & 0x000fFfffFfffFfffL sign = (bits >> 63) exponent = 1023 pm = '+' if sign == 0 else '' s = '%s(%+05d)0x%013x' % (pm, exponent, mantissa) return s def readable_string_to_float(s): assert len(s) == 23 pm = s[0] assert pm == '+' or pm == '' sign = 1 if pm == '' else 0 assert s[1] == '(' and s[7] == ')' e = s[2:7] exponent = int(e, 10) + 1023 assert 0 <= exponent < 0x7ff m = s[8:] assert m[:2] == '0x' mantissa = int(m, 16) bits = (sign << 63) + (exponent << 52) + mantissa return _double.longBitsToDouble(bits) Hans Meine wrote:
Am Dienstag, 08. April 2008 17:22:33 schrieb Ken Basye:
I've had this happen often enough that I found the first thing I did when an output difference arose was to print the FP in hex to see if the difference was "real" or just a formatting artifact.
Nice idea  is that code available somewhere / could you post it?
As a side note, there is a second big source of buglike experiences with the x86 architecture: floating point values are represented with a higher precision inside the FPU (e.g. 80 bits instead of 64), but that probably only matters for compiled programs where the compiler may (or may not) optimize intermediate, truncating FPU>memory operations away (which leads to differing results and is one of the most often reported "bugs" of the GCC optimizer).
participants (3)

Alan G Isaac

Hans Meine

Ken Basye