Tuesday, August 17, 2010

Floating Point Literal Conversion

IBM 402 Accounting Machine plug-board wiring. ...Image via Wikipedia
IBM 402 Accounting Machine
I read an un-cited article in Doctor Dobb's Journal (DDJ) called A Simple Matter of Conversion. I think that the article was well written about the problem of literal conversion of decimal (floating point) numbers. I will not bother to repeat the article suffice to say that it is interesting from a mathematical, and computer programming perspective.

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

Enhanced by Zemanta

4 comments :

Doctor Binary said...

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?

John Yeary said...

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.

John Yeary said...

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.

Doctor Binary said...

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.

Popular Posts