Link to home
Start Free TrialLog in
Avatar of qas
qas

asked on

Rounding numbers

Hi.

There is a form with 2 buttons.

Button1 OnClick event looks like this:

procedure TForm1.Button1Click(Sender: TObject);

   function RoundedAmount(R: double; D: Longint): Double;

      function SymbolOf(Nbr: Double): Double;
      begin
         if Nbr < 0 then
            Result := -1
         else
            Result := 1;
      end;

      function NbrExponentOf(Nbr: Double; Exponent: Integer): Double;
      begin
         Result := 1;

         while Exponent < 0 do
         begin
            Result := Result / Nbr;
            Exponent := Exponent + 1;
         end;

         while Exponent > 0 do
         begin
            Result := Result * Nbr;
            Exponent := Exponent - 1;

         end;
      end;


   var
      P: double;
      X: double;
      dNbrExp: double;

   begin
      P := SymbolOf(R) * 0.5;
      dNbrExp := NbrExponentOf(10, D);
      X := R * dNbrExp + P;
      Result := int(X) / dNbrExp;
   end;

begin
showmessage(FloatToStr(RoundedAmount(0.105, 2)));
end;



And here is Button2.OnClick event:


procedure TForm1.Button2Click(Sender: TObject);

   function RoundedAmount(R: double; D: Longint): Double;

      function SymbolOf(Nbr: Double): Double;
      begin
         if Nbr < 0 then
            Result := -1
         else
            Result := 1;
      end;

      function NbrExponentOf(Nbr: Double; Exponent: Integer): Double;
      begin
         Result := 1;

         while Exponent < 0 do
         begin
            Result := Result / Nbr;
            Exponent := Exponent + 1;
         end;

         while Exponent > 0 do
         begin
            Result := Result * Nbr;
            Exponent := Exponent - 1;

         end;
      end;


   var
      P: double;

   begin
      P := SymbolOf(R) * 0.5;
      Result := Int(R * NbrExponentOf(10, D) + P) / NbrExponentOf(10, D);
   end;

begin
showmessage(FloatToStr(RoundedAmount(0.105, 2)));
end;




The only difference is the inline "RoundedAmount" which is slightly different between Button1 and Button2.  "RoundedAmount" is supposed to round an amount of money  (No I CANNOT use any Delphi's Math functions like RoundTo.  The point isn't there anyways).  Here are the only differences between the 2 functions:

With Button2, I calculate RESULT on a single line:

      P := SymbolOf(R) * 0.5;
      Result := Int(R * NbrExponentOf(10, D) + P) / NbrExponentOf(10, D);  


With Button1, I calculate RESULT using multiple variables so it can stand on multiple lines:

      P := SymbolOf(R) * 0.5;
      dNbrExp := NbrExponentOf(10, D);
      X := R * dNbrExp + P;
      Result := int(X) / dNbrExp;


At first look, both functions should give the same result, right ?.  And that is my problem: IT DOES NOT!!
When I hit Button1 I get 0.11 and with Button2 I get 0.1.

My question is simple: why is that ?  How can I fix this ?
Avatar of DavidBirch2dotCom
DavidBirch2dotCom

I cant see the problem, however if you want to check out some of the delphi functions, to see if they do what they should, then I have found this site to be very useful

http://www.delphibasics.co.uk

David
Double, http://www.delphibasics.co.uk/RTL.asp?Name=Double
Extended http://www.delphibasics.co.uk/RTL.asp?Name=Extended
LongInt http://www.delphibasics.co.uk/RTL.asp?Name=LongInt
Int http://www.delphibasics.co.uk/RTL.asp?Name=Int

is it anything to do with when you are adding 'P' ? try sticking brackets into it...
Result := Int(R * (NbrExponentOf(10, D) + P)) / NbrExponentOf(10, D);  


Avatar of qas

ASKER

Thanks David

When you say that you dont see the problem, do you mean that you tried the code and everything worked fine or that it doesn't and you can't say why ?
sorry, looking over the code I couldnt see any thing except where you add P, I'll try the code in a moment, im trying to solve a problem of my own in delphi ;)

DAvid
Avatar of qas

ASKER

I placed the brackets in both functions and it didn't changed anything.

A problem in Delphi ?  Sorry, never happenned to me ;)
looking @ it now, cant see anything, but if you place brackets around the line
 X := R * dNbrExp + P;
in the first button like this
 X := R *( dNbrExp + P);

it will return .1  ? but change the line on button 2

 Result := Int( (R * NbrExponentOf(10, D)) + P) / NbrExponentOf(10, D);  

but it still returns 0.1 ?

DAvid
its something to do with the int function

      P := SymbolOf(R) * 0.5;
      B:=  NbrExponentOf(10, D);
      Result :=  Int((R *B) + P) ;
      Result := (result) / B

will give 0.1

      P := SymbolOf(R) * 0.5;
      B:=  NbrExponentOf(10, D);
      Result :=  ((R *B) + P) ;
      Result := Int(result) / B

give 0.11

it must be something to do with delphi.... is there anything on the borland website... *looking*

David
Avatar of qas

ASKER

Yes it's true.  I also tried it with trunk() with same result.
not sure if this helps but  according to http://www.efg2.com/Lab/Library/Delphi/MathFunctions/General.htm 

int will round DOWN to 0 which would explain it... it must be working out the int function (with 10.5) without adding the value of P (0.5)

which result did you get? what code?

David
Avatar of qas

ASKER


>which result did you get? what code?
I just replaced the int function with the trunc function (which should work the same way) and it gave me the same erroneous results (0.1 and 0.11).


It is normal that the int rounds down to 0.  That is actually why it is used in the function, to get rid of the remaining digits.  

The thing I can't understand is that if...

     ((R *B) + P) = 11

...and...

     Int(11) = 11

...why would...
   
     Int((R *B) + P) = 10 ??


Does ((R *B) + P) actually gives someting like 10.99999999... or what ?
ASKER CERTIFIED SOLUTION
Avatar of DavidBirch2dotCom
DavidBirch2dotCom

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of qas

ASKER

That is just great.  

How the hell am I supposed to get back to people telling me that Delphi sucks and VB rocks now ?  If that is the problem, Delphi DOES suck.  We're talking about basics here damnit !


Thanls a lot David for your help :)

thats the first time i have seen it do that , in every other time and function it works normaly, just a querk with that one function, its the first delphi bug ive come accross in 2-3 years.. of delphi.

personaly, from dabbles into VB from outlook and excel VB sucks ;) but i never really go into it so...

David
many thanks for the points :)
Avatar of qas

ASKER

My pleasure :)

Just a last question if you have a second.  Lets say I have:

P := 12;
P := 25;
showmessage(inttostr(P));


Delphi wont compile the first line since the assigned value aint used.  Can I force Delphi to compile it anyway ?  Maybe our problem is around such optimization...
erm, how would you tell if it did or didnt compile it ?

didnt know delphi didnt compile it?

DAvid
Avatar of qas

ASKER

Yes, Delphi kind of optimizes the code so that useless lines arent compiled at all.  

For example, make a function and never call it.  When you compile it, no little blue dots are drawn on the left margin.  The function wont be compiled.

Another example is to try the sample code:

P := 12;
P := 25;
showmessage(inttostr(P));

Try putting a Break Point on the 1st line, it wont stop on it.

If Delphi decides that some brackets are useless and removes them, there could be our problem.

But if you dont know how to remove the optimization, that is ok.  You helped me alot already :)

Thanks again!