Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Hour Span quirk 1

Status
Not open for further replies.

lespaul

Programmer
Feb 4, 2002
7,083
US
I am using HourSpan to calculate the amount of time a juror worked. I have a few people who return:
.50000000000001
which I want to be reported as just .5

is there any way to round to the 1st place?

Thanks!

Leslie
landrews@metrocourt.state.nm.us

There are 10 types of people in the world -
those who understand binary
and
those who don't!
 
Be careful with rounding in Delphi. It uses something called "banker's rounding" which handles .5 either up or down whichever results in an even number. Really weird. Also the Pascal Round function is brain-dead, as it only rounds to whole numbers.

Here is the function I use:
Code:
{Rounds a real number to the specified number of decimal places.}
function RoundN( const ANumber:real; const ADecimals:integer=0 ): real;
var
  nScale,nWork:real;
begin
  if ANumber = 0 then
    begin
      Result := 0;
    end
  else
    begin
      nScale := IntPower(10,ADecimals);
      nWork := Abs( ANumber * nScale );
      if nWork - Trunc(nWork) = 0.5 then
        nWork := nWork + 0.0000000001;  // Otherwise Delphi rounds to even number.
      Result := Round(nWork) / nScale;
      if ANumber < 0 then
        Result := - Result;
    end;
end;
 
For some reason, that returns 0 instead of my fraction 0.5. Any other suggestions?
Leslie
landrews@metrocourt.state.nm.us

There are 10 types of people in the world -
those who understand binary
and
those who don't!
 
Would FloatToDecimal not do the trick? I haven't used it though, saw it in the help.

lou
 
I don't know, maybe. I couldn't get the parameters correct to see! If anyone knows the proper format to call this function, please share!!

Thanks! Leslie
landrews@metrocourt.state.nm.us

There are 10 types of people in the world -
those who understand binary
and
those who don't!
 
lespaul,

Um, how about this?

Code:
procedure TForm1.Button1Click(Sender: TObject);
var
   dblInput : Double;
   strOutput : ShortString;
begin

   dblInput := StrToFloat( Edit1.Text );
   strOutput := format( '%5.2f', [ dblInput ] );
   label1.Caption := strOutput;

end;

Hope it helps...

-- Lance
 
except it's not an input, it's a calculation from a recordset: if the juror has the following time records
SERVDAT TIMETYPE TIMEIO
20030101 OI 830
20030101 OO 1030
20030106 TI 930
20030106 TO 1430
20030108 TI 1400
20030108 TO 1700

I have a process that transforms it into an array of TDateTimes:
1/1/2003 830 1030
1/6/2003 930 1430
1/8/2003 1400 1700

then HourSpan is used to calculate the amount of time to be paid for each day and then all the hours are totaled. My problem is that occassionally the total result is .5000000000001 and when this is transferred to my excel spreadsheet, the format is screwy! I have the excel sheet formatted to number, 2 decimals, but that's not working. I thought there would be a way to truncate/round the additional numbers.
Leslie
landrews@metrocourt.state.nm.us

There are 10 types of people in the world -
those who understand binary
and
those who don't!
 
lespaul, how did you define your variables? This works for me (displays 0.5 in the ShowMessage box):
Code:
procedure TfrmMain.Button1Click(Sender: TObject);
var
  nFunnyNumber: double;
  nCleanNumber: double;
begin;
  nFunnyNumber := 0.50000000000001;
  nCleanNumber := RoundN(nFunnyNumber,1);
  ShowMessage( FLoatToStr( nCleanNumber ));
end;
 
Zathras,

Thanks, I finally got it to work. I had to use it within another function that I'm calling. Once I put it in the right spot it worked like a charm!! Kudos & stars to you!
Leslie
landrews@metrocourt.state.nm.us

There are 10 types of people in the world -
those who understand binary
and
those who don't!
 
Glad to help, and thanks for the star.

BTW, footpad's solution does provide another way of doing it, but it still (sometimes) suffers from the funny rounding that Delphi is noted for:

e.g., .585 is displayed (correctly) as 0.59
but .575 is displayed (wrongly) as 0.57
however, changing the number of decimals in the mask:
5.85 is displayed as 5.9 and 5.75 is displayed as 5.8, both correct (stranger and stranger).

Which is really strange because Round() goes the other way:
e.g., Round(58.5) produces (wrongly) 58
and Round(57.5) produces (correctly) 58

It all makes me wonder if my function will always produce the correct results. -- Use with care.

As for weez's suggestion to use FloatToDecimal -- it wants a TFloatRec type as input, which is rather cumbersome to work with.
 
Since we're still testing all this, I'm sure that SOMEBODY will let me know if it doesn't work right!! But I'll keep an eye on it.

Thanks for your help. And yes, I found trying to get the FloatToDecimal hard to work with! Couldn't quite figure out what I was suppose to pass it!

la Leslie
landrews@metrocourt.state.nm.us

There are 10 types of people in the world -
those who understand binary
and
those who don't!
 
&quot;And yes, I found trying to get the FloatToDecimal hard to work with! Couldn't quite figure out what I was suppose to pass it!&quot;

Me too! [smile2]

lou
 
Just a note on why there is this Delphi &quot;bug&quot; for rounding.

The rounding rules for .5's have long been debated amongst scientists, and other nerds/important people to whom significant digits really do matter.

The latest and greatest theory / rule is exactly what Delphi does.

In the case of .5 roundings, you always round to the even number, be it down or up. So 57.15 goes to 57.2, and 57.25 goes to 57.2.

This is of course not what most of us would expect, but according to &quot;someone&quot;, it is the &quot;proper&quot; way of rounding.

Andrew
 
I've also heard it referred to &quot;banker's rounding&quot;, but that doesn't explain the inconsistency mentioned in my previous post (in at least one case, rounding to the nearest ODD number instead of the nearest EVEN number):

Using
Code:
 format( '%5.2f', [ dblInput ] );

produced the following results:
.585 is displayed as 0.59
.575 is displayed as 0.57
 
Greetings,

I was flipping through the Delphi 6 Help Index today and stumbled across something that might help:

Code:
uses Math;

procedure TForm1.Button1Click(Sender: TObject);
var
   dblInput,
   dblOutput : Double;
begin

   dblInput := StrToFloat( edit1.Text );
   dblOutput := simpleRoundTo( dblInput, -2 );
   label1.Caption := floatToStr( dblOutput );

end;

It looks like this was added in Delphi 6. It rounds the input to a power of ten. Also, the second parameter defaults to -2, so you can use
Code:
simpleRoundTo( dblInput );
to get basic currency-style rounding.

Also, a search on Borland's community site yielded an alternative that may help those using other Delphi versions. For details, see helpful.

Hope it helps...somehow...

-- Lance
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top