Recent

Author Topic: how to extract dicimal place  (Read 2040 times)

Packs

  • Sr. Member
  • ****
  • Posts: 492
how to extract dicimal place
« on: February 18, 2023, 10:24:47 am »
we want to find decimal value exist in the string value .

Example : '34.56'
this is having decimal value > 0 then we want t o print 13.56

Example : '34.00'
in this case we wan to print 34 only .

do we have ready made function in lazarus . I have to write custom function to solve this issue
 

440bx

  • Hero Member
  • *****
  • Posts: 6139
Re: how to extract dicimal place
« Reply #1 on: February 18, 2023, 11:34:59 am »
Example : '34.56'
this is having decimal value > 0 then we want t o print 13.56
13.56 ? ... is that a typo ?, if not, what rule is being applied that changes 34.56 into 13.56 ?
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Packs

  • Sr. Member
  • ****
  • Posts: 492
Re: how to extract dicimal place
« Reply #2 on: February 18, 2023, 12:06:11 pm »
yes it is typing mistake . it should be 34.56

Packs

  • Sr. Member
  • ****
  • Posts: 492
Re: how to extract dicimal place
« Reply #3 on: February 18, 2023, 12:21:42 pm »
Code: Pascal  [Select][+][-]
  1.  
  2. function CountDecimals(Value: string): string;
  3. var
  4.   s,s2: string;
  5.   p,nInt,nlen: integer;
  6. begin
  7.   nlen := Length(value);
  8.   p := pos(FormatSettings.DecimalSeparator, Value);
  9.   if p > 0 then
  10.   begin
  11.     s2 := copy(Value, p+1,nlen );
  12.  
  13.     nInt := StrToInt(s2);
  14.     if nInt > 0 then
  15.       result := Value
  16.     else
  17.       result := copy(Value, 1, p-1);;
  18.   end;
  19. end;
  20.  
I have created custom founction

Paolo

  • Hero Member
  • *****
  • Posts: 682
Re: how to extract dicimal place
« Reply #4 on: February 18, 2023, 12:52:53 pm »
And if the input is 13.50 you want as output 13.50 or 13.5 ?

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: how to extract dicimal place
« Reply #5 on: February 18, 2023, 02:09:20 pm »
I have created custom founction
It has errors.
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$IFDEF MSWINDOWS}{$APPTYPE CONSOLE}{$ENDIF}
  3.  
  4. uses
  5.   SysUtils;
  6.  
  7. type
  8.   TNumberType = (ntInvalid, ntFloat, ntInteger);
  9.   TNumber = record
  10.     FType: TNumberType;
  11.     FInteger: Integer;
  12.     FFloat: Double;
  13.     FString: string;
  14.   end;
  15.  
  16. function TryToNumber(const AValue: string; out AOut: TNumber): Boolean;
  17. var
  18.   i: Double;
  19.   s: string;
  20. begin
  21.   Result := False;
  22.   AOut.FType := ntInvalid;
  23.   AOut.FFloat := 0.0;
  24.   AOut.FInteger := 0;
  25.   AOut.FString := '0';
  26.   if TryStrToFloat(AValue, i) then
  27.     begin
  28.       if Frac(i) = 0.0 then
  29.         begin
  30.           AOut.FType := ntInteger;
  31.           AOut.FInteger := Trunc(i);
  32.           AOut.FString := IntToStr(Trunc(i));
  33.         end
  34.         else
  35.         begin
  36.           AOut.FType := ntFloat;
  37.           AOut.FFloat := i;
  38.           AOut.FString := FloatToStrF(i, ffFixed, 16, 2);
  39.         end;
  40.       Result := True;
  41.       Exit;
  42.     end;
  43.   if ((Pos('.', AValue) <> 0) and (FormatSettings.DecimalSeparator <> '.')) then
  44.     begin
  45.       s := AValue.Replace('.', ',', [rfReplaceAll]);
  46.       if TryStrToFloat(s, i) then
  47.         begin
  48.           if Frac(i) = 0.0 then
  49.             begin
  50.               AOut.FType := ntInteger;
  51.               AOut.FInteger := Trunc(i);
  52.               AOut.FString := IntToStr(Trunc(i));
  53.             end
  54.             else
  55.             begin
  56.               AOut.FType := ntFloat;
  57.               AOut.FFloat := i;
  58.               AOut.FString := FloatToStrF(i, ffFixed, 16, 2);
  59.             end;
  60.           Result := True;
  61.           Exit;
  62.         end;
  63.     end;
  64.   if ((Pos(',', AValue) <> 0) and (FormatSettings.DecimalSeparator <> ',')) then
  65.     begin
  66.       s := AValue.Replace(',', '.', [rfReplaceAll]);
  67.       if TryStrToFloat(s, i) then
  68.         begin
  69.           if Frac(i) = 0.0 then
  70.             begin
  71.               AOut.FType := ntInteger;
  72.               AOut.FInteger := Trunc(i);
  73.               AOut.FString := IntToStr(Trunc(i));
  74.             end
  75.             else
  76.             begin
  77.               AOut.FType := ntFloat;
  78.               AOut.FFloat := i;
  79.               AOut.FString := FloatToStrF(i, ffFixed, 16, 2);
  80.             end;
  81.           Result := True;
  82.           Exit;
  83.         end;
  84.     end;
  85. end;
  86.  
  87.  
  88. function CountDecimals(Value: string): string;
  89. var
  90.   s,s2: string;
  91.   p,nInt,nlen: integer;
  92. begin
  93.   nlen := Length(value);
  94.   p := pos(FormatSettings.DecimalSeparator, Value);
  95.   if p > 0 then
  96.   begin
  97.     s2 := copy(Value, p+1,nlen );
  98.  
  99.     nInt := StrToInt(s2);
  100.     if nInt > 0 then
  101.       result := Value
  102.     else
  103.       result := copy(Value, 1, p-1);;
  104.   end;
  105. end;
  106.  
  107. var
  108.   s: string;
  109.   LNum: TNumber;
  110. begin
  111.   WriteLn('');
  112.   WriteLn('KodeZwerg:');
  113.   WriteLn('');
  114.  
  115.   s := '12.34';
  116.   if TryToNumber(s, LNum) then
  117.     WriteLn(s, ' -> ', LNum.FString)
  118.     else
  119.     WriteLn(s, ' could not be converted!');
  120.  
  121.   s := '56,78';
  122.   if TryToNumber(s, LNum) then
  123.     WriteLn(s, ' -> ', LNum.FString)
  124.     else
  125.     WriteLn(s, ' could not be converted!');
  126.  
  127.   s := '9.00';
  128.   if TryToNumber(s, LNum) then
  129.     WriteLn(s, ' -> ', LNum.FString)
  130.     else
  131.     WriteLn(s, ' could not be converted!');
  132.  
  133.   s := '99,00';
  134.   if TryToNumber(s, LNum) then
  135.     WriteLn(s, ' -> ', LNum.FString)
  136.     else
  137.     WriteLn(s, ' could not be converted!');
  138.  
  139.   s := 'abc';
  140.   if TryToNumber(s, LNum) then
  141.     WriteLn(s, ' -> ', LNum.FString)
  142.     else
  143.     WriteLn(s, ' could not be converted!');
  144.  
  145.   WriteLn('');
  146.   WriteLn('Team Prakash:');
  147.   WriteLn('');
  148.  
  149.   s := '12.34';
  150.   WriteLn(s, ' -> ', CountDecimals(s));
  151.   s := '56,78';
  152.   WriteLn(s, ' -> ', CountDecimals(s));
  153.   s := '9.00';
  154.   WriteLn(s, ' -> ', CountDecimals(s));
  155.   s := '99,00';
  156.   WriteLn(s, ' -> ', CountDecimals(s));
  157.   s := 'abc';
  158.   WriteLn(s, ' -> ', CountDecimals(s));
  159. {$IFDEF MSWINDOWS}ReadLn; {$ENDIF}
  160. end.
Output:
Quote
KodeZwerg:

12.34 -> 12,34
56,78 -> 56,78
9.00 -> 9
99,00 -> 99
abc could not be converted!

Team Prakash:

12.34 ->
56,78 -> 56,78
9.00 -> 56,78
99,00 -> 99
abc -> 99
And if the input is 13.50 you want as output 13.50 or 13.5 ?
In my case you still have values and be able to format however you want.
By default I round to two digits after seperator to having a same look (for floats)
« Last Edit: February 18, 2023, 02:11:25 pm by KodeZwerg »
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

jamie

  • Hero Member
  • *****
  • Posts: 7597
Re: how to extract dicimal place
« Reply #6 on: February 18, 2023, 03:22:31 pm »
Code: Pascal  [Select][+][-]
  1. Function ValidDecOnly(S:String; aPad:Boolean=False):String;
  2. Var
  3.   I:Integer;
  4. Begin
  5.   I:= Pos(FormatSettings.DecimalSeparator,S);
  6.   If I<>0 Then
  7.   Begin
  8.    IF StrTOInt(Copy(S,I+1,4)+'0')=0 Then
  9.      Result := Copy(S,1,I-1)
  10.    else
  11.    Begin
  12.      Result := S;
  13.      // Optional padding;
  14.      If APad Then
  15.      While Length(Copy(Result,I+1,4))<2 DO Result := Result+'0';
  16.    end;
  17.   end else Result := S;
  18. end;                                        
  19.  

I think that should do what you need.
The only true wisdom is knowing you know nothing

Kays

  • Hero Member
  • *****
  • Posts: 632
  • Whasup!?
    • KaiBurghardt.de
Re: how to extract decimal place
« Reply #7 on: February 18, 2023, 04:58:32 pm »
Sigh. One fundamental mistake: Your implementations are attempting to convert a string into a numeric value. The “correct” implementation: You need to perform string inspection only. Example: '-99999999999999999999.000' should yield '-99999999999999999999' (despite any potential overflows).

Prakash has not stated he intends to perform calculations “with strings”, nor has it been established the given strings strictly draw from the domain of real or integer.

The easiest solution is a one-liner using tStringHelper:
Code: Pascal  [Select][+][-]
  1. uses
  2.         sysUtils;
  3. var
  4.         s: ANSIString;
  5. begin
  6.         s := '-99999999999999999999.000';
  7.         writeLn(s.trimRight('0.'));
  8. end.
« Last Edit: February 18, 2023, 05:00:44 pm by Kays »
Yours Sincerely
Kai Burghardt

jamie

  • Hero Member
  • *****
  • Posts: 7597
Re: how to extract dicimal place
« Reply #8 on: February 18, 2023, 05:24:12 pm »
It would be better of course to scan right to left using POS. I've seen cases where the separator for the thousands is also the same for the fractions, but only 2 digits.

So, one could extend PosEX to use a -1 as the starting position to indicate a scan right to left should be done or any (-) offset starting from the right to left.

  I don't see anything in the docs about this being able to perform this option now, so I assume it does not.

 I think this would be better than creating a new function just for this.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018