Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2014-07

formatfloat negative zero (-0)

12 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Andrea Mauri

Dear all,

using formatfloat function I got an unexpected behaviour. If I round negative numbers I can get as result of formatfloat = '-0'. I think it is a bug, since -0 has no meaning, zero is zero. How can I make a workaround?
e.g.
label1.Caption:= FormatFloat('0.###', strtofloat(edit1.Text)); if in edit1.text I have -0.000001 I got -0 as result while I would like to get 0.

Is it a bug, what can I do?

Best regards,
Andrea Mauri

Lazarus 1.2.5 r45573M FPC 2.6.4 i386-win32-win32/win64

Reply by email

Lukasz Sokol
to Andrea Mauri
Andrea Mauri wrote 11 lines
Dear all, using formatfloat function I got an unexpected behaviour. If I round negative numbers I can get as result of formatfloat = '-0'. I think it is a bug, since -0 has no meaning, zero is zero. How can I make a workaround? e.g. label1.Caption:= FormatFloat('0.###', strtofloat(edit1.Text)); if in edit1.text I have -0.000001 I got -0 as result while I would like to get 0. Is it a bug, what can I do?

Minus-zero is a recognized computational 'feature' of floats on computers, not a bug (AFAIK).

The float variable value of StrToFloat(edit1.text) is still -0.000001 though;
(try assigning it to a float type variable and watch it)

Does the same happen if you Round() it to integer? e.g.
label1.caption := Format('%d',[Round(strtofloat(edit1.text))]); (I know this isn't what you're after

Best regards, Andrea Mauri

-L.

Reply by email

Andrea Mauri
to Lukasz Sokol
Show quoted text 15 lines
> > using formatfloat function I got an unexpected behaviour. > If I round negative numbers I can get as result of formatfloat = '-0'. > I think it is a bug, since -0 has no meaning, zero is zero. > How can I make a workaround? > e.g. > label1.Caption:= FormatFloat('0.###', strtofloat(edit1.Text)); > if in edit1.text I have -0.000001 I got -0 as result while I would like to get 0. > > Is it a bug, what can I do? Minus-zero is a recognized computational 'feature' of floats on computers, not a bug (AFAIK). The float variable value of StrToFloat(edit1.text) is still -0.000001 though; (try assigning it to a float type variable and watch it)

OK, I understand that computationally -0 has meaning (since as you said the float variable value of StrToFloat(edit1.text) is still -0.000001). Anyway It has no meaning for the final user of the application (at least for any standard user of an application).
The final user does not care that -0 has meaning for the computer. e.g. I would like to represent a float value with 3 decimal digits. I don't care of the remaining digits, -0.000 has no meaning, it just means that there are some digits (somewhere after the third decimal digits) that are not equal to zero and that if they are considered the value is negative (but I don't want to consider any digit after the third decimal one!).
Try to do it in excel or libreoffice:
- write in a cell -0.00001 and set to 3 the decimal digits, you got -0.000 or 0.000?
And you got the same results using any software that deals with numbers..

Show quoted text 5 lines
Does the same happen if you Round() it to integer? e.g. label1.caption := Format('%d',[Round(strtofloat(edit1.text))]); (I know this isn't what you're after

In this way I got 0.
Anyway I used as example formatfloat since it has the same behaviour of TFloatField.DisplayFormat, additionally DisplayFormat is a property that is used to represent a formatted value to the final user (a human being not a pc) for whom -0 has no meaning.

A.

Show quoted text 15 lines
> > Best regards, > Andrea Mauri > -L. -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Dmitry Boyarintsev
to Andrea Mauri

Will straight forward solution work?
how about this:

unit MySysUtils;
interface
uss SysUtils;
// the function will cut heading "-" if all digits in the number are zeros.
// it will leave the result unchanged otherwise.
function FormatFloat(const fmt: string; num: double): string;
var
  i : integer;
begin
  Result:= SysUtils.FormatFloat(fmt, num);
  if (Result'') and (Result[1]='-1') then begin
    for i:=2 to length(Result) do
     if Result[i] in ['1'..'9'] then Exit;
    Result:=Copy(Result, 2, length(Result)-1);
  end;

end;
....
in your program. Put "MySysUtils" as the last unit in the uses section (so your working unit would use MySysUtils FormatFloat, instead of the implementation at SysUtils)

thanks,
Dmitry

Andrea Mauri wrote 75 lines
>> using formatfloat function I got an unexpected behaviour. >> If I round negative numbers I can get as result of formatfloat = '-0'. >> I think it is a bug, since -0 has no meaning, zero is zero. >> How can I make a workaround? >> e.g. >> label1.Caption:= FormatFloat('0.###', strtofloat(edit1.Text)); >> if in edit1.text I have -0.000001 I got -0 as result while I would like >> to get 0. >> >> Is it a bug, what can I do? >> > > Minus-zero is a recognized computational 'feature' of floats on > computers, not a bug (AFAIK). > > The float variable value of StrToFloat(edit1.text) is still -0.000001 > though; > (try assigning it to a float type variable and watch it) > OK, I understand that computationally -0 has meaning (since as you said the float variable value of StrToFloat(edit1.text) is still -0.000001). Anyway It has no meaning for the final user of the application (at least for any standard user of an application). The final user does not care that -0 has meaning for the computer. e.g. I would like to represent a float value with 3 decimal digits. I don't care of the remaining digits, -0.000 has no meaning, it just means that there are some digits (somewhere after the third decimal digits) that are not equal to zero and that if they are considered the value is negative (but I don't want to consider any digit after the third decimal one!). Try to do it in excel or libreoffice: - write in a cell -0.00001 and set to 3 the decimal digits, you got -0.000 or 0.000? And you got the same results using any software that deals with numbers.. > Does the same happen if you Round() it to integer? > e.g. > label1.caption := Format('%d',[Round(strtofloat(edit1.text))]); > (I know this isn't what you're after > In this way I got 0. Anyway I used as example formatfloat since it has the same behaviour of TFloatField.DisplayFormat, additionally DisplayFormat is a property that is used to represent a formatted value to the final user (a human being not a pc) for whom -0 has no meaning. A. > >> Best regards, >> Andrea Mauri >> >> -L. > > > > -- > _______________________________________________ > Lazarus mailing list > > http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus > > -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20140707/8672c605/attachment-0001.html>

Reply by email

Philippe
to Dmitry Boyarintsev
if (Result'') and (Result[1]='-1') then begin

maybe ( '-1' ->
'-' )

if (Result'') and (Result[1]='-') then begin

?

Em

Dmitry Boyarintsev wrote
Will straight forward

solution work? how about this:

Show quoted text 9 lines
unit MySysUtils; interface uss SysUtils; // the function will cut heading "-" if all

digits in the number are zeros.

// it will leave the result unchanged

otherwise.

function FormatFloat(const fmt: string; num: double):
string;
var i : integer; begin Result:=
SysUtils.FormatFloat(fmt, num);
if (Result'') and (Result[1]='-1')

then begin

for i:=2 to length(Result) do if Result[i] in
['1'..'9'] then Exit;
Result:=Copy(Result, 2, length(Result)-1);
end;
end; .... in your program. Put "MySysUtils" as the last

unit in the uses section (so your working unit would use MySysUtils FormatFloat, instead of the implementation at SysUtils)

thanks,

Dmitry

On Mon, Jul 7, 2014 at 5:00 PM, Andrea Mauri
>>> using formatfloat function I

got an unexpected behaviour.

>>> If I round negative numbers I can get

as result of formatfloat = '-0'.

>>> I think it is a bug, since -0 has

no meaning, zero is zero.

>>> How can I make a workaround? >>>

e.g.

>>> label1.Caption:= FormatFloat('0.###',
strtofloat(edit1.Text));
>>> if in edit1.text I have -0.000001 I got -0

as result while I would like to get 0.

>>> >>> Is it a bug, what can

I do?

>> >> Minus-zero is a recognized computational 'feature' of

floats on computers, not a bug (AFAIK).

>> >> The float variable
value of StrToFloat(edit1.text) is still -0.000001 though;
>> (try

assigning it to a float type variable and watch it)

> OK, I understand

that computationally -0 has meaning (since as you said the float variable value of StrToFloat(edit1.text) is still -0.000001).

> Anyway

It has no meaning for the final user of the application (at least for any standard user of an application).

> The final user does not care

that -0 has meaning for the computer.

> e.g. I would like to represent

a float value with 3 decimal digits. I don't care of the remaining digits, -0.000 has no meaning, it just means that there are some digits (somewhere after the third decimal digits) that are not equal to zero and that if they are considered the value is negative (but I don't want to consider any digit after the third decimal one!).

> Try to do it in

excel or libreoffice:

> - write in a cell -0.00001 and set to 3 the

decimal digits, you got -0.000 or 0.000?

> And you got the same results

using any software that deals with numbers..

> >> Does the same

happen if you Round() it to integer?

>> e.g. >> label1.caption :=
Format('%d',[Round(strtofloat(edit1.text))]);
>> (I know this isn't

what you're after

> In this way I got 0. > Anyway I used as example

formatfloat since it has the same behaviour of
TFloatField.DisplayFormat, additionally DisplayFormat is a property that is used to represent a formatted value to the final user (a human being not a pc) for whom -0 has no meaning.

Show quoted text 5 lines
> > A. --

Reply by email

Dmitry Boyarintsev
to Philippe

Very true, sorry for the typo.
I meant give an idea, not an actual solution.
Plus it might won't work, if FormatFloat is not called directly, but rather by a 3d party component.

thanks,
Dmitry

Philippe wrote 139 lines
if (Result'') and (Result[1]='-1') then begin maybe ( '-1' -> '-' ) if (Result'') and (Result[1]='-') then begin ? Em 07.07.2014 10:48, Dmitry Boyarintsev escreveu: Will straight forward solution work? how about this: unit MySysUtils; interface uss SysUtils; // the function will cut heading "-" if all digits in the number are zeros. // it will leave the result unchanged otherwise. function FormatFloat(const fmt: string; num: double): string; var i : integer; begin Result:= SysUtils.FormatFloat(fmt, num); if (Result'') and (Result[1]='-1') then begin for i:=2 to length(Result) do if Result[i] in ['1'..'9'] then Exit; Result:=Copy(Result, 2, length(Result)-1); end; end; .... in your program. Put "MySysUtils" as the last unit in the uses section (so your working unit would use MySysUtils FormatFloat, instead of the implementation at SysUtils) thanks, Dmitry On Mon, Jul 7, 2014 at 5:00 PM, Andrea Mauri wrote: > >>> using formatfloat function I got an unexpected behaviour. >>> If I round negative numbers I can get as result of formatfloat = '-0'. >>> I think it is a bug, since -0 has no meaning, zero is zero. >>> How can I make a workaround? >>> e.g. >>> label1.Caption:= FormatFloat('0.###', strtofloat(edit1.Text)); >>> if in edit1.text I have -0.000001 I got -0 as result while I would like >>> to get 0. >>> >>> Is it a bug, what can I do? >> >> >> Minus-zero is a recognized computational 'feature' of floats on >> computers, not a bug (AFAIK). >> >> The float variable value of StrToFloat(edit1.text) is still -0.000001 >> though; >> (try assigning it to a float type variable and watch it) > > OK, I understand that computationally -0 has meaning (since as you said > the float variable value of StrToFloat(edit1.text) is still -0.000001). > Anyway It has no meaning for the final user of the application (at least > for any standard user of an application). > The final user does not care that -0 has meaning for the computer. > e.g. I would like to represent a float value with 3 decimal digits. I > don't care of the remaining digits, -0.000 has no meaning, it just means > that there are some digits (somewhere after the third decimal digits) that > are not equal to zero and that if they are considered the value is negative > (but I don't want to consider any digit after the third decimal one!). > Try to do it in excel or libreoffice: > - write in a cell -0.00001 and set to 3 the decimal digits, you got > -0.000 or 0.000? > And you got the same results using any software that deals with numbers.. > > > >> Does the same happen if you Round() it to integer? >> e.g. >> label1.caption := Format('%d',[Round(strtofloat(edit1.text))]); >> (I know this isn't what you're after > > In this way I got 0. > Anyway I used as example formatfloat since it has the same behaviour of > TFloatField.DisplayFormat, additionally DisplayFormat is a property that is > used to represent a formatted value to the final user (a human being not a > pc) for whom -0 has no meaning. > > A. > > > >> >>> Best regards, >>> Andrea Mauri >>> >>> -L. >> >> >> >> -- >> _______________________________________________ >> Lazarus mailing list >> >> http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus >> >> > -- > _______________________________________________ > Lazarus mailing list > > http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus > -- _______________________________________________ Lazarus mailing ://lists.lazarus.freepascal.org/mailman/listinfo/lazarus -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20140707/4d496974/attachment.html>

Reply by email

Lukasz Sokol
to Dmitry Boyarintsev

Hello Dymitry & Andrea,

(see my answer below)

Dmitry Boyarintsev wrote 104 lines
Very true, sorry for the typo. I meant give an idea, not an actual solution. Plus it might won't work, if FormatFloat is not called directly, but rather by a 3d party component. thanks, Dmitry On Mon, Jul 7, 2014 at 6:31 PM, Philippe < <mailto:>> wrote: __ if (Result'') and (Result[1]='-1') then begin maybe ( '-1' -> '-' ) if (Result'') and (Result[1]='-') then begin ? Em 07.07.2014 10:48, Dmitry Boyarintsev escreveu: > Will straight forward solution work? > how about this: > > unit MySysUtils; > > interface > > uss SysUtils; > > // the function will cut heading "-" if all digits in the number are zeros. > // it will leave the result unchanged otherwise. > > function FormatFloat(const fmt: string; num: double): string; > var > i : integer; > begin > Result:= SysUtils.FormatFloat(fmt, num); > if (Result'') and (Result[1]='-1') then begin > for i:=2 to length(Result) do > if Result[i] in ['1'..'9'] then Exit; > Result:=Copy(Result, 2, length(Result)-1); > end; > > end; > .... > in your program. Put "MySysUtils" as the last unit in the uses section (so your working unit would use MySysUtils FormatFloat, instead of the implementation at SysUtils) > > thanks, > Dmitry > > > > On Mon, Jul 7, 2014 at 5:00 PM, Andrea Mauri < <mailto:>> wrote: > > > using formatfloat function I got an unexpected behaviour. > If I round negative numbers I can get as result of formatfloat = '-0'. > I think it is a bug, since -0 has no meaning, zero is zero. > How can I make a workaround? > e.g. > label1.Caption:= FormatFloat('0.###', strtofloat(edit1.Text)); > if in edit1.text I have -0.000001 I got -0 as result while I would like to get 0. > > Is it a bug, what can I do? > > > Minus-zero is a recognized computational 'feature' of floats on computers, not a bug (AFAIK). > > The float variable value of StrToFloat(edit1.text) is still -0.000001 though; > (try assigning it to a float type variable and watch it) > > OK, I understand that computationally -0 has meaning (since as you said the float variable value of StrToFloat(edit1.text) is still -0.000001). > Anyway It has no meaning for the final user of the application (at least for any standard user of an application). > The final user does not care that -0 has meaning for the computer. > e.g. I would like to represent a float value with 3 decimal digits. I don't care of the remaining digits, -0.000 has no meaning, it just means that there are some digits (somewhere after the third decimal digits) that are not equal to zero and that if they are considered the value is negative (but I don't want to consider any digit after the third decimal one!). > Try to do it in excel or libreoffice: > - write in a cell -0.00001 and set to 3 the decimal digits, you got -0.000 or 0.000? > And you got the same results using any software that deals with numbers.. > > > > Does the same happen if you Round() it to integer? > e.g. > label1.caption := Format('%d',[Round(strtofloat(edit1.text))]); > (I know this isn't what you're after > > In this way I got 0. > Anyway I used as example formatfloat since it has the same behaviour of TFloatField.DisplayFormat, additionally DisplayFormat is a property that is used to represent a formatted value to the final user (a human being not a pc) for whom -0 has no meaning. > > A. > > > > > Best regards, > Andrea Mauri > > -L.

(p.s. please avoid top-posting unless you have to...)

I think manipulating this in string is also wrong on some levels.

What you need is a function that eats away the value but still does it in a float compute, like

function EatFloatBelow(Num : double; DecimalPlaces: Integer; EatSign:boolean=true): double;
var Temp : Integer;
begin
  (* Preprocess the float for displaying with fixed decimal places
   * if Num is smaller than 10**DecimalPlaces, it should also eat the sign by default
   * WARNING some of this function is pseudocode please check for proper variables *)
(* DecimalPlaces is supposed to be positive *)
  if DecimalPlaces < 0 then exit;
  (* preflight checks : check that DecimalPlaces is sane *)
  if 10**(-DecimalPlaces) < DoublePrecision then exit;  (* or Power(10,(-DecimalPlaces)) *)
  Temp := RoundDown(Num*(10**DecimalPlaces)); // first 'shift it' left and get rid of the remaining decimals by rounding down to integer
  Result := Temp / (10**DecimalPlaces);   // now restore the proper order and back to float
  (* can also combine the above 2 steps and use one less variable
   * Result := Trunc(Num*(10**DecimalPlaces)) / (10**DecimalPlaces) ; *)
  (* if we ended with something close to zero but still negative, eat the sign *)
  if (Result < 0) and EatSign and (Result < 10**(-DecimalPlaces))  then
    Result := Result * (-1) ;
end;
then use
label1.Caption:= FormatFloat('0.###', EatFloat(strtofloat(edit1.Text),3));

-L.

Reply by email

Andrea Mauri
to Lukasz Sokol
Show quoted text 36 lines
I think manipulating this in string is also wrong on some levels. What you need is a function that eats away the value but still does it in a float compute, like function EatFloatBelow(Num : double; DecimalPlaces: Integer; EatSign:boolean=true): double; var Temp : Integer; begin (* Preprocess the float for displaying with fixed decimal places * if Num is smaller than 10**DecimalPlaces, it should also eat the sign by default * WARNING some of this function is pseudocode please check for proper variables *) (* DecimalPlaces is supposed to be positive *) if DecimalPlaces < 0 then exit; (* preflight checks : check that DecimalPlaces is sane *) if 10**(-DecimalPlaces) < DoublePrecision then exit; (* or Power(10,(-DecimalPlaces)) *) Temp := RoundDown(Num*(10**DecimalPlaces)); // first 'shift it' left and get rid of the remaining decimals by rounding down to integer Result := Temp / (10**DecimalPlaces); // now restore the proper order and back to float (* can also combine the above 2 steps and use one less variable * Result := Trunc(Num*(10**DecimalPlaces)) / (10**DecimalPlaces) ; *) (* if we ended with something close to zero but still negative, eat the sign *) if (Result < 0) and EatSign and (Result < 10**(-DecimalPlaces)) then Result := Result * (-1) ; end; then use label1.Caption:= FormatFloat('0.###', EatFloat(strtofloat(edit1.Text),3)); -L.

Dear Lukasz,
thanks, anyway I reported this problem using formatfloat just because it has the same behaviour of TFloatField.DisplayFormat and it was easier to provide a sample code. I do not use FormatFloat so I cannot use your function.

As I wrote I think that this behaviour is a bug and not a feature (see excel and libreoffice behaviour). Someone can check the delphi behaviour?

Andrea

Reply by email

Lukasz Sokol
to Andrea Mauri
Andrea Mauri wrote 14 lines
> Dear Lukasz, thanks, anyway I reported this problem using formatfloat just because it has the same behaviour of TFloatField.DisplayFormat and it was easier to provide a sample code. I do not use FormatFloat so I cannot use your function. As I wrote I think that this behaviour is a bug and not a feature (see excel and libreoffice behaviour). Someone can check the delphi behaviour? Andrea

As a matter of fact, I can... on Turbo Delphi 2006 (free edition)...

and the behavior is as you said it should be.

(i.e. FormatFloat eats the minus if the content of the edit is smaller than expected by the format string)

With FormatFloat format string '0.###' :

Input: -0.001 Output: -0.001
Input: -0.0001 Output: 0.000

So it _is_ not the same as Lazarus/FPC has;

Guess it's time to call to the bugtracker then...

-L.

Reply by email

Andrea Mauri
to Lukasz Sokol

Il 09/07/2014 13:44, Lukasz Sokol ha scritto:

Show quoted text 16 lines
As a matter of fact, I can... on Turbo Delphi 2006 (free edition)... and the behavior is as you said it should be. (i.e. FormatFloat eats the minus if the content of the edit is smaller than expected by the format string) With FormatFloat format string '0.###' : Input: -0.001 Output: -0.001 Input: -0.0001 Output: 0.000 So it_is_ not the same as Lazarus/FPC has; Guess it's time to call to the bugtracker then... -L.

Ok. Reported to the bugtracker, ID 0026465.
Thanks,
Andrea

Reply by email

Dmitry Boyarintsev
to Andrea Mauri

Hello Andrea,

I thing it would worth mentioning Delphi's behavior? And the bug report is also missing a patch to fix the problem :)

thanks,
Dmitry

Andrea Mauri wrote 35 lines
Il 09/07/2014 13:44, Lukasz Sokol ha scritto: > As a matter of fact, I can... on Turbo Delphi 2006 (free edition)... > > and the behavior is as you said it should be. > > (i.e. FormatFloat eats the minus if the content of the edit is smaller > than expected by the format string) > > With FormatFloat format string '0.###' : > > Input: -0.001 Output: -0.001 > Input: -0.0001 Output: 0.000 > > So it_is_ not the same as Lazarus/FPC has; > > > Guess it's time to call to the bugtracker then... > > -L. > Ok. Reported to the bugtracker, ID 0026465. Thanks, Andrea -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20140709/2b418495/attachment.html>

Reply by email

Andrea Mauri
to Dmitry Boyarintsev
I thing it would worth mentioning Delphi's behavior?

I mentioned Delphi behaviour, it is the reason that it is considered a bug and not a feature..

And the bug report is also missing a patch to fix the problem :)

I know. I reported the bug but sorry but I am not able to provide a patch, I used the bugtracker as a bugtracker, I highlighted the bug ;-)

Reply by email