Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   float con coma (,) o punto (.) (https://www.clubdelphi.com/foros/showthread.php?t=77730)

lmpadron 22-02-2012 21:00:40

float con coma (,) o punto (.)
 
Saludos

Hola comunidad, estoy realizando un programilla de la siguiente forma tengo dos edits en uno el usuario inserta un numero de tipo float, despues yo lo resto contra otro float que defino directamente dentro del codigo y asigno el resultado al segundo edit.

El primer edit recibe el número y en su evento KeyPress hago lo siguiente
Código:

void __fastcall TForm6::DBEdit9KeyPress(TObject *Sender, char &Key)
{
  if(Key == '.')
  {
    Key = ',';
  }
}

sustituyo los puntos en caso de que el usuario lo presione por comas para poder calcular sin que me de error

En el evento Change lo siguiente
Código:

void __fastcall TForm6::DBEdit9Change(TObject *Sender)
{         
          float a,b,c;
          b = Round(StrToFloat(Edit1->Text),2);
          c = 7.33;

          if (b == c)
          {
                DBEdit2->Text = "0";
          }
          else
          {
                if (b > c)
                {
                        MessageDlg("Upsss lo siento !!!!, el número A es mayor al numero B",mtInformation, TMsgDlgButtons() << mbOK, 0);
                }
                else
                {
                        a = c - b;
                        Edit2->Text = FloatToStr(Round(a,2));
                }
          }
}

El otro es que al insertarse el valor en el edit 1 necesito sustituir los puntos por comas para que no me de error. En mi pc me funciona correctamente de la forma en que aqui lo expongo o sea usando como separador para el decimal la coma y de hecho si pongo un punto me devuelve un error diciendo que no es un valor flotante valido, sin embargo en las pc donde lo pruebo necesita todo el tiempo como separador para los decimales el punto.

En conclusion :
1 En mi pc el separador decimal es la coma, de otra forma a error en la conversion.

2 En la otra pc el separador decimal es el punto. De otra forma da error.

3 Al asignar un valor en el codigo a la variable C tengo que hacerlo usando como separador decimal el punto sino tampoco en mi pc funciona o sea da error.

Pregunta
Cual es el separador decimal en c, el punto o la coma?

P.D.
Realmente no entiendo como puede funcionar bien el mismo codigo en una pc y en otra no.

Gracias de antemano por su respuesta

ecfisa 22-02-2012 21:15:40

Cita:

Pregunta
Cual es el separador decimal en c, el punto o la coma?
Hola Impadrón.

Revisá si te sirve este hilo

Un saludo.

lmpadron 22-02-2012 21:37:50

Cita:

Empezado por ecfisa (Mensaje 425815)
Hola Impadrón.

Revisá si te sirve este hilo

Un saludo.

Gracias por responder ecfisa el problema es que el numero que uso nunca llega a los millares porque es una decena o sea 7.33 especificamente, si el usuario inserta algo mayor no se realizara la conversion.
De paso el codigo funciona perfecto en mi maquina con la coma, pero no en la de el usuario que estoy probando, de paso si lo pongo con el punto le funciona perfecto al usuario pero a mi no me funciona. Lo que no entiendo es que quieres decir con esto:
Cita:

Empezado por ecfisa (Mensaje 404984)
Código:

  Aux = "125.000,12";
  Aux.Delete(Aux.Pos('.'),1);
  StrToFloat(Aux);


Cuando es que pasa por esa conversion, tengo que realizarla yo, quien es AUX ?
Existe alguna forma de definir cual es el separador decimal interno para que no me de error al efectuar la conversion ?

gersojn 22-02-2012 22:02:22

Obtencion de Input Locale
 
Te doy una solucion a tu problema, no es la mas optima para implementarla, pero te puede dar una idea para partir de ahi, algo mas formal.

Dejar que la aplicacion decida cuando aplicar "," o "." , lo cual dependera de que Input tenga el PC donde lo ejecutes. Para obtener el separador decimal utilizas NumberFormatInfo(No recuerdo como instanciarlo, pero sangoogle, siempre sabe todo), dependiendo de si te retorne una "," o "." operas en tu aplicacion.

Saludos

gersojn 22-02-2012 22:15:30

Otra solucion
 
Cita:

Empezado por gersojn (Mensaje 425821)
Te doy una solucion a tu problema, no es la mas optima para implementarla, pero te puede dar una idea para partir de ahi, algo mas formal.

Dejar que la aplicacion decida cuando aplicar "," o "." , lo cual dependera de que Input tenga el PC donde lo ejecutes. Para obtener el separador decimal utilizas NumberFormatInfo(No recuerdo como instanciarlo, pero sangoogle, siempre sabe todo), dependiendo de si te retorne una "," o "." operas en tu aplicacion.

Saludos

Investigando sobre un problema que debo de resolver, encontre algo que te pueda ser mucho mas util.
Mediante un registry, puedes determinar cual es el decimal utilizado en la PC. Voy a implementarlo en codigo, para mi aplicacion.
y posteo el codigo. Saludos

lmpadron 22-02-2012 22:41:23

Cita:

Empezado por gersojn (Mensaje 425823)
(...) encontre algo que te pueda ser mucho mas util. (...) Voy a implementarlo en codigo (...) y posteo el codigo. Saludos

OK muchas gracias de paso estube buscando el numberformatinfo y no lo he encontrado en bcb sin embargo si aparece en visual estudio de hecho la mayor parte de las referencias son de ellos.
Espero a que lo implementes y postees !!!

escafandra 22-02-2012 22:50:46

Cita:

Empezado por lmpadron (Mensaje 425818)
Gracias por responder ecfisa el problema es que el numero que uso nunca llega a los millares...

Creo que no has entendido la sugerencia de ecfisa:
Cita:

Empezado por ecfisa (Mensaje 404984)
Código:

  DecimalSeparator = '.';  // muestra: 125.000.12
  // o
  DecimalSeparator = ',';  // muestra: 125.000,12


Cita:

Empezado por lmpadron (Mensaje 425818)
...Existe alguna forma de definir cual es el separador decimal interno para que no me de error al efectuar la conversion ?

Código:

  DecimalSeparator = '.';  // Si quieres que sea el punto
  DecimalSeparator = ',';  // Si quieres que sea la coma

Saludos.

gersojn 22-02-2012 22:59:58

Solucion Optima y Viable
 
Cita:

Empezado por escafandra (Mensaje 425828)
Creo que no has entendido la sugerencia de ecfisa:



Código:

  DecimalSeparator = '.';  // Si quieres que sea el punto
  DecimalSeparator = ',';  // Si quieres que sea la coma

Saludos.

Hola, veras, para realizar el calculo sin que tengas problemas, efectivamente debes realizar la conversion Internamente(para que el usuario no lo perciba y trabaje a comodidad) o bien, externamente.

El codigo para obtener cual es el decimal en una PC es el siguiente

OJO: Incluyes la libreria

#include <Registry.hpp> Para que no te de problema

Código:


TRegistry *regKey = new TRegistry;
        regKey->Access =KEY_READ;
        regKey->RootKey  = HKEY_USERS;
        regKey->OpenKey(".DEFAULT\\Control Panel\\International", true);
        mostrar->Caption = regKey->ReadString("sDecimal");

//mostrar es un label donde reflejo en cuestion cual es el valor

        regKey->CloseKey();

Teniendo el simbolo ya tu haces comparacion si una "," que haga esto, si es "." que haga esto otro.

Saludos.

ecfisa 23-02-2012 05:54:24

Hola.

Los valores actuales de los formatos de la configuración regional, también se pueden obtener consultando directamente las variables.

Ejemplo:
Código:

void __fastcall TForm1::Button1Click(TObject *Sender) {
char const* MSGE = "Separador %s: [ %s ]";

  ShowMessage(
    Format(MSGE, ARRAYOFCONST(("decimal ",DecimalSeparator))) +'\n'+
    Format(MSGE, ARRAYOFCONST(("de miles",ThousandSeparator))) +'\n'+
    Format(MSGE, ARRAYOFCONST(("de fecha",DateSeparator))) +'\n'+
    Format(MSGE, ARRAYOFCONST(("de lista  ",ListSeparator)))
    //...
  );
}

Saludos.

roman 23-02-2012 06:45:41

Cita:

Empezado por lmpadron (Mensaje 425811)
El primer edit recibe el número y en su evento KeyPress hago lo siguiente
Código:

void __fastcall TForm6::DBEdit9KeyPress(TObject *Sender, char &Key)
{
  if(Key == '.')
  {
    Key = ',';
  }
}


Jamás deberías hacer una cosa así. Jamás. Tu código debe respetar las preferencias regionales del usuario, en este caso, el separador que usen para los decimales, coma o punto. No deberías tener que preocuparte por cuál caracter introduce el usuario. La función StrToFloat se encarga de eso y para ello utiliza el valor de la variable global DecimalSeparator. Dicho valor se establece en la inicialización de la unidad SysUtils haciendo una consulta a la configuración regional establecida en el sistema. Tú no deberías alterar el valor de dicha variable y, ni siquiera debería preocuparte saber su valor.

Si el usuario tiene configurado el sistema para usar una coma como separador decimal y oprime un punto, es problema del usuario, tú no debes tratar de adivinar lo que él quería hacer, simplemente dejas que el sistema le marque el error:

Cita:

'4.83' is not a valid floating point value.
A lo sumo, interceptas la excepción para dar un mensaje en español o más amigable:

Código Delphi [-]
var
  a: Double;

begin
  try
    a := StrToFloat(Edit1.Text);
  except
    on EConvertError do
      raise Exception.CreateFmt('%s no es un número flotante válido', [Edit1.Text]);
  end;
end;

En resumen, tu pregunta en este hilo ni siquiera debería darse. No lo digo por molestar, sino para enfatizar el hecho de que tu código no debería preocuparse por esto.

// Saludos

escafandra 23-02-2012 08:13:53

Cita:

Empezado por roman (Mensaje 425853)
Jamás deberías hacer una cosa así. Jamás. Tu código debe respetar las preferencias regionales del usuario, en este caso, el separador que usen para los decimales, coma o punto. ...

...En resumen, tu pregunta en este hilo ni siquiera debería darse. No lo digo por molestar, sino para enfatizar el hecho de que tu código no debería preocuparse por esto.

La apreciación de roman es muy cierta. Códigos como el que expones puede dar lugar a incertidumbre y frustración en el usuario. Nunca debes cambierle su configuración aunque puedes leerla tranquilamente.

Sin embargo no veo mal que exponga sus dudas pues el tema es útil desde el punto de vista didáctico. Ha servido para que tanto lmpadron como otros en su situación, se den cuenta de la existencia de distintas configuraciones del separador decimal y otros, como bien apunta ecfisa, y de pié al sabio consejo de roman.


Saludos.

lmpadron 23-02-2012 16:24:59

Cita:

Empezado por roman (Mensaje 425853)
Jamás deberías hacer una cosa así. Jamás. Tu código debe respetar las preferencias regionales del usuario

Román, como dices, algo así no debería hacerse y lo de respetar la configuración del usuario esta más que claro sin embargo los usuarios que van a usar este software deben insertar aproximadamente 3000 planillas en solo 8 horas por ende han solicitado que sea de la forma mas cómoda posible, lanzar un mensaje de error los haría primeramente tener que parar de insertar los datos además estarían forzados a usar la coma del teclado que es mucho mas incomoda cuando insertamos números dado que generalmente lo hacemos desde el área numérica del teclado (en caso de que esa sea su configuración).

Después de leer tu post reuní a los futuros usuarios y los puse al tanto del asunto y todos estuvieron de acuerdo en que hiciera lo que fuera necesario para que sea mas simple y cómoda la inserción de los datos en la base de datos.

Cita:

Empezado por roman (Mensaje 425853)
No lo digo por molestar, sino para enfatizar el hecho de que tu código no debería preocuparse por esto.

No se preocupe, nunca es molestia recibir un consejo y mas aun cuando es tan tan bueno.

Cita:

Empezado por gersojn (Mensaje 425830)
Hola, veras, para realizar el calculo sin que tengas problemas, efectivamente debes realizar la conversion Internamente(para que el usuario no lo perciba y trabaje a comodidad) o bien, externamente.

La solución de gersojn es muy buena pero no quisiera modificar el registro de todos mis usuarios y usar esa solución para determinar que esta usando como separador decimal y después efectuar el cambio es un problema inmenso ya que aunque mi soft se adapte a cada pc aun así estarían escribiendo en la base de datos los decimales con puntos o comas según su configuración y seria después muy molesto hacer algún calculo.

Cita:

Empezado por escafandra (Mensaje 425828)
Creo que no has entendido la sugerencia de ecfisa

Pues si, tenias toda la razón realmente no la había entendido pero después de revisarla he decidido hacer la conversión interna como indica ecfisa y asi no modificar las preferencias regionales de los usuarios de acuerdo al consejo de Román

Cita:

Empezado por ecfisa (Mensaje 404984)
Código:

  DecimalSeparator = '.';  // muestra: 125.000.12
  // o
  DecimalSeparator = ',';  // muestra: 125.000,12


Al final el codigo ha quedado asi

Código:

void __fastcall TForm6::DBEdit9Change(TObject *Sender)
{         
          DecimalSeparator = '.'
          float a,b,c;
          b = Round(StrToFloat(Edit1->Text),2);
          c = 7.33;

          if (b == c)
          {
                DBEdit2->Text = "0";
          }
          else
          {
                if (b > c)
                {
                        MessageDlg("Upsss lo siento !!!!, el número A es mayor al numero B",mtInformation, TMsgDlgButtons() << mbOK, 0);
                }
                else
                {
                        a = c - b;
                        Edit2->Text = FloatToStr(Round(a,2));
                }
          }
}

De esta forma me funciona perfecto.

Quiciera agradecerles a todos los que me han ayudado a averiguar finalmente cual es el separador decimal en los float :D jamas imaginarme que estaba en el registro, eso explica porque el mismo código funcionaba perfecto en una pc y muy mal en otras. De paso he aprendido que existe DecimalSeparator para este tipo de casos.

Gracia a todos por prestarme su ayuda y su tiempo

roman 23-02-2012 17:46:54

No creo que tenga caso colocar la asignación

Código:

DecimalSeparator = '.'
en el evento OnChange. Colócala en el constructor del formulario o en alguna parte similar al comienzo de tu aplicación.

// Saludos

Chris 23-02-2012 20:35:31

Cita:

Empezado por lmpadron (Mensaje 425886)
Román, como dices, algo así no debería hacerse y lo de respetar la configuración del usuario esta más que claro sin embargo los usuarios que van a usar este software deben insertar aproximadamente 3000 planillas en solo 8 horas por ende han solicitado que sea de la forma mas cómoda posible, lanzar un mensaje de error los haría primeramente tener que parar de insertar los datos además estarían forzados a usar la coma del teclado que es mucho mas incomoda cuando insertamos números dado que generalmente lo hacemos desde el área numérica del teclado (en caso de que esa sea su configuración).

Lo de mostrar un MessageBox ya lo hemos discutido. Ahora, con respecto a la comodidad del usuario y el punto que toca Román -súper importante-. Ve, asignarle directamente un valor a las variables como DecimalSeparator no es recomendable. Para hacer las conversiones, a cómo ha dicho Román, basta con un StrToFloat. Pero quieres que el divisor del punto flotante sea con . -punto-. Puedes hacer esto con StrToFloat se forma muy sencilla. Fíjate (código en Delphi):

Código Delphi [-]
var
    FS: TFormatSettings;
    NumberAsFloat: Double;
begin
    FS.DecimalSeparator := '.'; // usar . para punto decimal
    
    try
        NumberAsFloat := StrToFloat(Edit1.Text, FS); // el ultimo parametro
                                                     // es el que hace la magia
    except on EValueError do
        ShowBalloonTip ...
    end;
    
    ..
end;

¿Viste que fácil y claro el código?

Saludos!


La franja horaria es GMT +2. Ahora son las 16:48:21.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi