2009-04-25 12 views
8

¿Hay una función Delphi incorporada que convierta una cuerda como '3,232.00' para flotar? StrToFloat genera una excepción debido a la coma. ¿O es la única manera de quitar la coma primero y luego hacer StrToFloat?Convertir cadena con comas para flotar

Gracias.

+3

¿Hay algún requisito para que esto funcione en lugares donde se utiliza la coma como separador decimal? En cualquier lugar de Europa, por ejemplo? –

Respuesta

15

¿Sabes exactamente que '.' es un separador decimal y ',' es un separador de miles (siempre)? Si es así, debe completar el registro TFormatSettings y pasarlo a StrToFloat.

FillChar(FS, SizeOf(FS), 0); 
... // filling other fields 
FS.ThousandSeparator := ','; 
FS.DecimalSeparator := '.'; 
V := StrToFloat(S, FS); 
+2

Suponiendo que está en Delphi 7 o superior, de lo contrario, el argumento de configuración de formatos no está disponible, y StrToFloat ignora felizmente cualquier milseparador que configura –

+0

¿'FillChar (FS, SizeOf (FS), 0);' realmente es necesario? Parece que funciona también sin (Delphi XE2). – user1580348

+0

@ user1580348 Sí, es necesario. Puede funcionar, pero solo por coincedense. Es decir: o bien se completan TODOS los campos (y no se agregan nuevos campos en la próxima versión de Delphi), o StrToFloat no utiliza una basura que está en FS. Controle Delphi RTL: debe poner a cero los campos no utilizados. – Alex

4

Probar: StrToFloat(StringReplace('3,232.00', ',', '') Debe deshacerse de las comas antes de realizar la conversión.

En C#/VB.NET utilizo usaría algo así como decimal.convert("3,232.00", ",", "");

No conozco ninguna manera de hacer la conversión sin eliminar los caracteres adicionales. De hecho, tengo una función especial en mi biblioteca que elimina las comas y los símbolos de moneda. Así que una llamada real MyConverer.decimalConverter("$3,232.00");

+0

Eso no se compila. StringReplace tiene un 4º parámetro; 'Flags' – awmross

+1

Simplemente ponga [] en el parámetro flags: StrToFloat (StringReplace ('3,232.00', ',', '', []) –

8

a continuación es lo que uso. podría haber formas más eficientes, pero esto funciona para mí. En resumen, no, no sé de cualquier función Delphi integrado que convierte una cadena de flotador que contiene comas para un flotador

{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    safeFloat 

    Strips many bad characters from a string and returns it as a double. 
} 
function safeFloat(sStringFloat : AnsiString) : double; 
var 
    dReturn : double; 

begin 
    sStringFloat := stringReplace(sStringFloat, '%', '', [rfIgnoreCase, rfReplaceAll]); 
    sStringFloat := stringReplace(sStringFloat, '$', '', [rfIgnoreCase, rfReplaceAll]); 
    sStringFloat := stringReplace(sStringFloat, ' ', '', [rfIgnoreCase, rfReplaceAll]); 
    sStringFloat := stringReplace(sStringFloat, ',', '', [rfIgnoreCase, rfReplaceAll]); 
    try 
    dReturn := strToFloat(sStringFloat); 
    except 
    dReturn := 0; 
    end; 
    result := dReturn; 

end; 
+4

Para que esto funcione también en otras configuraciones regionales: Reemplace ',' en la última línea de stringReplace con ThousandSeparator. – mghie

+0

También puede reemplazar el símbolo de dólar con CurrencyString para otros locales. http://tinyurl.com/cwvu37 – stukelly

0

que tenían el mismo problema cuando mis usuarios tienen que introducir 'científico' valores tales como "1,234.06mV". Aquí hay una coma, un multiplicador (m = x0.001) y una unidad (V). Creé una rutina de convertidor de formato "ancho" para manejar estas situaciones. Brian

4
function StrToFloat_Universal(pText : string): Extended; 
const 
    EUROPEAN_ST = ','; 
    AMERICAN_ST = '.'; 
var 
    lformatSettings : TFormatSettings; 
    lFinalValue  : string; 
    lAmStDecimalPos : integer; 
    lIndx   : Byte; 
    lIsAmerican  : Boolean; 
    lIsEuropean  : Boolean; 

begin 
    lIsAmerican := False; 
    lIsEuropean := False; 
    for lIndx := Length(pText) - 1 downto 0 do 
    begin 
    if (pText[ lIndx ] = AMERICAN_ST) then 
    begin 
     lIsAmerican := True; 
     pText := StringReplace(pText, ',', '', [ rfIgnoreCase, rfReplaceAll ]); //get rid of thousand incidental separators 
     Break; 
    end; 
    if (pText[ lIndx ] = EUROPEAN_ST) then 
    begin 
     lIsEuropean := True; 
     pText := StringReplace(pText, '.', '', [ rfIgnoreCase, rfReplaceAll ]); //get rid of thousand incidental separators 
     Break; 
    end; 
    end; 
    GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, lformatSettings); 
    if (lformatSettings.DecimalSeparator = EUROPEAN_ST) then 
    begin 
    if lIsAmerican then 
    begin 
     lFinalValue := StringReplace(pText, '.', ',', [ rfIgnoreCase, rfReplaceAll ]); 
    end; 
    end; 
    if (lformatSettings.DecimalSeparator = AMERICAN_ST) then 
    begin 
    if lIsEuropean then 
    begin 
     lFinalValue := StringReplace(pText, ',', '.', [ rfIgnoreCase, rfReplaceAll ]); 
    end; 
    end; 
    pText := lFinalValue; 
    Result := StrToFloat(pText, lformatSettings); 
end; 
1

que utiliza una función que es capaz de manejar la '', y el '' como decimalSeparator ...:

function ConvertToFloat(aNr: String; aDefault:Integer): Extended; 
var 
    sNr, s3R, sWhole, sCent:String; 
    eRC:Extended; 
begin 
    sNr:=ReplaceStr(sNr, ' ', ''); 

    if (Pos('.', sNr) > 0) or (Pos(',', sNr) > 0) then 
    begin 
    // Get 3rd character from right 
    s3R:=LeftStr(RightStr(sNr, 3), 1); 
    if s3R <> DecimalSeparator then 
    begin 
     if not IsNumber(s3R) then 
     begin 
     s3R := DecimalSeparator; 
     sWhole := LeftSr(sNr, Length(sNr) - 3); 
     sCent := (RightStr(sNr, 2); 
     sNr := sWhole + DecimalSeparator + sCent; 
     end 
     else 
     // there are no decimals... add ',00' 
     sNr:=sNr + DecimalSeparator + '00'; 
    end; 
    // DecimalSeparator is present; get rid of other symbols 
    if (DecimalSeparator = '.') and (Pos(',', sNr) > 0) then sNr:=ReplaceStr(sNr, ',', ''); 
    if (DecimalSeparator = ',') and (Pos('.', sNr) > 0) then sNr:=ReplaceStr(sNr, '.', ''); 
    end; 

    eRc := StrToFloat(sNr); 
end; 
0

Myfunction:

function StrIsFloat2 (S: string; out Res: Extended): Boolean; 
var 
    I, PosDecimal: Integer; 
    Ch: Char; 
    STrunc: string; 
    liDots, liComma, J: Byte; 
begin 
    Result := False; 
    if S = '' 
    then Exit; 
    liDots := 0; 
    liComma := 0; 
    for I := 1 to Length(S) do begin 
    Ch := S[I]; 
    if Ch = FormatSettings.DecimalSeparator then begin 
     Inc (liDots); 
     if liDots > 1 then begin 
     Exit; 
     end; 
    end 
    else if (Ch = '-') and (I > 1) then begin 
     Exit; 
    end 
    else if Ch = FormatSettings.ThousandSeparator then begin 
     Inc (liComma); 
    end 
    else if not CharIsCipher(Ch) then begin 
     Exit; 
    end; 
    end; 
    if liComma > 0 then begin 
    PosDecimal := Pos (FormatSettings.DecimalSeparator, S); 
    if PosDecimal = 0 then 
     STrunc := S 
    else 
     STrunc := Copy (S, 1, PosDecimal-1); 
    if STrunc[1] = '-' then 
     Delete (S, 1, 1); 
    if Length(STrunc) < ((liComma * 3) + 2) then 
     Exit; 
    J := 0; 
    for I := Length(STrunc) downto 1 do begin 
     Inc(J); 
     if J mod 4 = 0 then 
     if STrunc[I] <> FormatSettings.ThousandSeparator then 
      Exit; 
    end; 
    S := ReplaceStr (S, FormatSettings.ThousandSeparator, ''); 
    end; 
    try 
    Res := StrToFloat (S); 
    Result := True; 
    except 
    Result := False; 
    end; 
end; 
Cuestiones relacionadas