Image via Wikipedia |
IBM 402 Accounting Machine |
The article mentions the work of William D. Clinger on floating point conversion. His article is called How to Read Floating Point Numbers Accurately which is linked here.
The article also mentions the work of Guy L. Steele and Jon L. White entitled How to Print Floating-Point Numbers Accurately. This includes a great deal of technical mathematics, but is very well written.
The article also refers to algorithms written by David M. Gay which are implementations of how to produce accurate results. His C based code is located in a source file called dtoa.c. This code is public domain for your use provided you attribute the code as noted in the comments.
I thought I would give it a try in Java on my Mac and see what the results would be without any conversion in the spirit of Mr. Gay's algorithm.
I was surprised that I did not get strange results. My numeric values printed exactly what it should have. I would need to check the code on Java 1.5 to see if there is a difference. I thought it produced a different answer. Perhaps someone else will give it a try and let me know.
/* * Copyright 2010 Blue Lotus Software, LLC. * Copyright 2010 John Yeary <jyeary@bluelotussoftware.com>. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * under the License. */ /* * $Id: Main.java 276 2010-08-18 16:53:46Z jyeary $ */ package com.bluelotussoftware.example.fp; /** * * @author John Yeary <jyeary@bluelotussoftware.com> * @version 1.0 */ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { float f = 0.1f; System.out.println("f: " + f); String fp = Float.toString(f); System.out.println("fp: " + fp); float fpx = Float.valueOf(fp); System.out.println("fpx: " + fpx); float f1 = (float) (1f / 53f); System.out.println("f1: " + f1); System.out.println("f1: " + Float.valueOf(Float.toString(f1))); String f1x = ("f1x:" + f1); float f1f = Float.parseFloat(f1x.split(":")[1]); System.out.println("f1f: " + f1f); float f2 = (float) 19f / 27f; System.out.println("f2: " + f2); float f3 = (float) 8f / 27f; System.out.println("f3: " + f3); String f2p = Float.toString(f2); System.out.println("f2p: " + f2p); System.out.println("f2+f3: " + (f2 + f3)); System.out.println("f2p+f3: " + (Float.valueOf(f2p) + f3)); } }
run: f: 0.1 fp: 0.1 fpx: 0.1 f1: 0.018867925 f1: 0.018867925 f1f: 0.018867925 f2: 0.7037037 f3: 0.2962963 f2p: 0.7037037 f2+f3: 1.0 f2p+f3: 1.0 BUILD SUCCESSFUL (total time: 0 seconds)
Here is a link to my NetBeans project: FloatingPointExample.zip
4 comments :
John,
Try something other than 1/8, since that is exactly representable in binary. Here's your output for 1/3:
0.1
0.1
0.1
0.33333334
0.33333334
0.333
0.3333333432674408
0.33333334
Does that still give you what you expect?
Ahhh...my old arch nemesis the good Doctor Binary. Just kidding. I do like the name. It would be a cool evil villain name.
You are correct in that the representation can be done in binary so the results are skewed.
I will modify my code and example download to reflect your comments.
Doctor Binary... I have added some additional code examples, and I uploaded a new version of my NB project.
I did note that when I created new values that they added correctly, but this is due to rounding.
I think java does its decimal string to floating-point conversions correctly, according to my testing (unlike Visual C++ or GCC/GLIBC). And I don't think it uses David Gay's code either. As for conversion from floating-point to decimal strings, I haven't tested it, so I don't know how well it does.
Post a Comment