Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 563
  • Last Modified:

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 ?
0
qas
Asked:
qas
  • 10
  • 7
1 Solution
 
DavidBirch2dotComCommented:
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
0
 
DavidBirch2dotComCommented:
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);  


0
 
qasAuthor Commented:
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 ?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
DavidBirch2dotComCommented:
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
0
 
qasAuthor Commented:
I placed the brackets in both functions and it didn't changed anything.

A problem in Delphi ?  Sorry, never happenned to me ;)
0
 
DavidBirch2dotComCommented:
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
0
 
DavidBirch2dotComCommented:
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
0
 
qasAuthor Commented:
Yes it's true.  I also tried it with trunk() with same result.
0
 
DavidBirch2dotComCommented:
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
0
 
qasAuthor Commented:

>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 ?
0
 
DavidBirch2dotComCommented:
I think that the int function only works on the (R *B) for some unkown reason... Borland dont know thier BODMAS ;)  (BODMAS = Brackets Over Division Multiplaction Addition Subtraction)
0
 
qasAuthor Commented:
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 :)

0
 
DavidBirch2dotComCommented:
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
0
 
DavidBirch2dotComCommented:
many thanks for the points :)
0
 
qasAuthor Commented:
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...
0
 
DavidBirch2dotComCommented:
erm, how would you tell if it did or didnt compile it ?

didnt know delphi didnt compile it?

DAvid
0
 
qasAuthor Commented:
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!



0

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

  • 10
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now