Solved

Rounding numbers

Posted on 2004-08-12
17
527 Views
Last Modified: 2010-04-05
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
Comment
Question by:qas
  • 10
  • 7
17 Comments
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11786936
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
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11786984
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
 

Author Comment

by:qas
ID: 11787204
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
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11787240
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
 

Author Comment

by:qas
ID: 11787290
I placed the brackets in both functions and it didn't changed anything.

A problem in Delphi ?  Sorry, never happenned to me ;)
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11787328
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
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11787401
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
 

Author Comment

by:qas
ID: 11787427
Yes it's true.  I also tried it with trunk() with same result.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11787452
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
 

Author Comment

by:qas
ID: 11787667

>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
 
LVL 7

Accepted Solution

by:
DavidBirch2dotCom earned 250 total points
ID: 11787748
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
 

Author Comment

by:qas
ID: 11788001
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
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11788035
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
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11788044
many thanks for the points :)
0
 

Author Comment

by:qas
ID: 11788115
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
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11788151
erm, how would you tell if it did or didnt compile it ?

didnt know delphi didnt compile it?

DAvid
0
 

Author Comment

by:qas
ID: 11788310
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now