[Mono-list] Problem converting a string to double

Marcus Vinicius Eiffle Duarte Marcus Vinicius Eiffle Duarte <eiffleduarte@gmail.com>
Wed, 29 Dec 2004 11:10:06 -0200


I am a Mono newbie and this may be a real stupid question.
I am running Mono 1.0 on Fedora Core 1, setup to Brazilian locale.

I am beginning to port the front-end of a scientific application from
C to C# and intend to use Mono+C#+GTK# to get user input,
read/pase/write data and P/Invoke the mathematical back-end written in
C.

I have lots of data files, with all my data stored in CSV format. So,
I wrote a class to open a file, read its lines, split the fields and
fill a matrix with its values. In this process, I invoke the
String.ToDouble method to convert the strings read from the file to
double values. The problem is that the ToDouble method is giving weird
results, ignoring the (default) point decimal separator.

For instance, there is a sample output from the last line of a small
datafile, showing line number, column number, string representing the
value and the value converted with ToDouble:

aux = 13, aux2 = 0, colunas[0] = 14, matriz[13,0] = 14
aux = 13, aux2 = 1, colunas[1] = 18.015, matriz[13,1] = 18015
aux = 13, aux2 = 2, colunas[2] = 647.3, matriz[13,2] = 6473
aux = 13, aux2 = 3, colunas[3] = 221.2, matriz[13,3] = 2212
aux = 13, aux2 = 4, colunas[4] = 0.0571, matriz[13,4] = 571
aux = 13, aux2 = 5, colunas[5] = 0.235, matriz[13,5] = 235
aux = 13, aux2 = 6, colunas[6] = 0.344, matriz[13,6] = 344
aux = 13, aux2 = 7, colunas[7] = 32.24, matriz[13,7] = 3224
aux = 13, aux2 = 8, colunas[8] = 0.001924, matriz[13,8] = 1924
aux = 13, aux2 = 9, colunas[9] = 1.055e-05, matriz[13,9] = 0,01055
aux = 13, aux2 = 10, colunas[10] = -3.596e-09, matriz[13,10] = -3,596E-06
aux = 13, aux2 = 11, colunas[11] = -242000, matriz[13,11] = -242000
aux = 13, aux2 = 12, colunas[12] = 373.2, matriz[13,12] = 3732

For aux2=8, the string read is 0.001924, but ToDouble(0.001924) gives
1924. And so on

The only way to get a correct result is using
ToDouble(strvalue,provider), with provider set as

     NumberFormatInfo provider = new NumberFormatInfo( );
     provider.NumberDecimalSeparator = ".";

With this code, I get

aux = 13, aux2 = 0, colunas[0] = 14, matriz[13,0] = 14
aux = 13, aux2 = 1, colunas[1] = 18.015, matriz[13,1] = 18,015
aux = 13, aux2 = 2, colunas[2] = 647.3, matriz[13,2] = 647,3
aux = 13, aux2 = 3, colunas[3] = 221.2, matriz[13,3] = 221,2
aux = 13, aux2 = 4, colunas[4] = 0.0571, matriz[13,4] = 0,0571
aux = 13, aux2 = 5, colunas[5] = 0.235, matriz[13,5] = 0,235
aux = 13, aux2 = 6, colunas[6] = 0.344, matriz[13,6] = 0,344
aux = 13, aux2 = 7, colunas[7] = 32.24, matriz[13,7] = 32,24
aux = 13, aux2 = 8, colunas[8] = 0.001924, matriz[13,8] = 0,001924
aux = 13, aux2 = 9, colunas[9] = 1.055e-05, matriz[13,9] = 1,055E-05
aux = 13, aux2 = 10, colunas[10] = -3.596e-09, matriz[13,10] = -3,596E-09
aux = 13, aux2 = 11, colunas[11] = -242000, matriz[13,11] = -242000
aux = 13, aux2 = 12, colunas[12] = 373.2, matriz[13,12] = 373,2

Which is the expected and printed with the brazilian setup's comma
decimal separator, instead of the point which I coded into the class.

My question is: should it be really necessary to set the culture
information to perform such a simple task, when the decimal separator
is the default point? I thought I would only have to do it if I was
using a localized decimal separetor (as the portuguese-style comma).
Is this the expected behavior? Or the environmental locale should
really affect the internal conversion?

Thanks in advance,

Marcus Vinicius

P.S.: The demo code is below (with NumberFormatInfo) :

// created on 28/12/2004 at 13:34
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Globalization;

public class ReadData
{
	public static void Main(string [] args)
	{
		string filename = "compostos.csv";
		string[] colunas;
		string[] linhas;
		string text;
		int aux, aux2;
		NumberFormatInfo provider = new NumberFormatInfo( );
		
		provider.NumberDecimalSeparator = ".";
        
		using (TextReader reader = File.OpenText(filename))
		{
			text = reader.ReadToEnd();
			linhas = text.Split('\n');
		}
		Console.WriteLine(text);
		colunas = linhas[0].Split(',');
				
		int nlinhas = linhas.GetLength(0) - 1;
		int ncolunas = colunas.GetLength(0);
		
		for(aux = 0; aux < ncolunas; aux++)
		{
			Console.Write("{0}, ",colunas[aux]);
		}
		Console.WriteLine();
	
		double[,] matriz = new double[nlinhas, ncolunas];
		
		for(aux = 0; aux < nlinhas; aux++)
		{
			if(aux > 0)
			{
				colunas = linhas[aux].Split(',');
			}
			for(aux2 = 0; aux2 < ncolunas; aux2++)
			{
				matriz[aux, aux2] = System.Convert.ToDouble(colunas[aux2],provider);
				Console.WriteLine("aux = {0}, aux2 = {1}, colunas[{1}] = {2},
matriz[{0},{1}] = {3}",aux,aux2,colunas[aux2],matriz[aux,aux2]);
			}
		}
	}
}