Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Strange results when converting string to float

Moderators: kris

Posted: 07/09/10 16:57:53

Last week I had to process some CSV files (btw. tango.io.stream.Quotes is real cool) and I came across some inconsistencies when converting strings to (float/real) numbers.

To sum it up:
1. I did expect a float (not a real) as result of text.convert.Float.parse
2. text.convert.Float happily converts several things that IMHO aren't numbers
3. util.Convert fails on "0E0"
4. why is it that "-0" becomes -0 but "-0x0" becomes 0?

I made a little test program (using Tangobos for phobos std.conv)

module conv;

import tango.io.Stdout;
import Float    = tango.text.convert.Float;
import Convert  = tango.util.Convert;

import Phobos   = std.conv;

int main (char[][] args)
{
    // types
    Stdout.formatln("Types:\n  convert.Float -> {}\n  util.Convert  -> {}\n", 
            typeof(Float.parse("1")).stringof,
            typeof(Convert.to!(float)("1")).stringof
            );
    
    // results
    char[][] strings = 
             [ 
                "", "-", ".", "-.", "*",
                "E", "-E",
                "0E0", "-0E0",
                "0E1", "1E0",
                "2E0", "2E0.5",
                "0x", "x0", "-x0",
                "0", "-0",
                "0x0", "-0x0",
                "0x1", "-0x1", 
             ];
    
    Stdout.formatln("Results:");
    foreach(i, s; strings)
    {
        auto f = Float.parse(s);
        auto g = Convert.to!(float)(s, float.nan);
        float p;
        try
        {
            p = Phobos.toFloat(s);
        }
        catch(Object o)
        {
            p = float.nan;
        }
        
        Stdout.formatln("{:d3}: '{}'", 1+i, s);
        Stdout.formatln("  convert.Float: {}",
                            Float.toString(f));
        Stdout.formatln("  util.Convert:  {}",
                            Float.toString(g));
        Stdout.formatln("  std.conv:      {}\n",
                            Float.toString(p));
    }
    return 0;
}

and it gave me these results:

Types:
  convert.Float -> real
  util.Convert  -> float

Results:
001: ''
  convert.Float: nan
  util.Convert:  nan
  std.conv:      nan

002: '-'
  convert.Float: nan
  util.Convert:  nan
  std.conv:      nan

003: '.'
  convert.Float: 0
  util.Convert:  0
  std.conv:      nan

004: '-.'
  convert.Float: -0
  util.Convert:  -0
  std.conv:      nan

005: '*'
  convert.Float: 0
  util.Convert:  nan
  std.conv:      nan

006: 'E'
  convert.Float: 0
  util.Convert:  nan
  std.conv:      nan

007: '-E'
  convert.Float: -0
  util.Convert:  nan
  std.conv:      nan

008: '0E0'
  convert.Float: 0
  util.Convert:  nan
  std.conv:      0

009: '-0E0'
  convert.Float: -0
  util.Convert:  nan
  std.conv:      -0

010: '0E1'
  convert.Float: 0
  util.Convert:  nan
  std.conv:      0

011: '1E0'
  convert.Float: 1
  util.Convert:  1
  std.conv:      1

012: '2E0'
  convert.Float: 2
  util.Convert:  2
  std.conv:      2

013: '2E0.5'
  convert.Float: 2
  util.Convert:  nan
  std.conv:      nan

014: '0x'
  convert.Float: nan
  util.Convert:  nan
  std.conv:      nan

015: 'x0'
  convert.Float: 0
  util.Convert:  nan
  std.conv:      nan

016: '-x0'
  convert.Float: -0
  util.Convert:  nan
  std.conv:      nan

017: '0'
  convert.Float: 0
  util.Convert:  0
  std.conv:      0

018: '-0'
  convert.Float: -0
  util.Convert:  -0
  std.conv:      -0

019: '0x0'
  convert.Float: 0
  util.Convert:  0
  std.conv:      nan

020: '-0x0'
  convert.Float: 0
  util.Convert:  0
  std.conv:      nan

021: '0x1'
  convert.Float: 1
  util.Convert:  1
  std.conv:      nan

022: '-0x1'
  convert.Float: -1
  util.Convert:  -1
  std.conv:      nan
Author Message

Posted: 07/17/10 17:58:08

Can't say why util.Convert would be different than convert.Float -- maybe danielkeep can answer that one. As for the others, I suspect Float.parse() is indicating it didn't eat/consume anything for some of these inputs? When that happens it will set the second argument appropriately, whereas it appears phobos throws an exception instead?

I see in your tests that the second argument to Float.parse() is not being used. However, perhaps nan should be returned for such conditions regardless?