Recent

Author Topic: [SOLVED] Why doesn't the 'int' function return an integer value?  (Read 1742 times)

McDoob

  • Newbie
  • Posts: 6
[SOLVED] Why doesn't the 'int' function return an integer value?
« on: November 13, 2024, 09:25:57 pm »
Hello, world.

I am confused by FPC's refusal to understand my intent:

  if (MaxVal mod NumSegments = 0)
    then SegmentVal:=MaxVal div NumSegments
    else SegmentVal:= int(MaxVal/NumSegments);

Error: Incompatible types: got "Double" expected "LongInt"

Having already perused the forum, I've changed my vars to double...but...

  FullSegments:=CurVal div SegmentVal;

Error: Operator is not overloaded: "LongInt" div "Double"

Oh, right, Because being NOT overloaded is a reason to complain? o_O
Whiskey Tango Foxtrot, over?
« Last Edit: November 13, 2024, 11:22:33 pm by McDoob »

Warfley

  • Hero Member
  • *****
  • Posts: 1763
Re: Why doesn't the 'int' function return an integer value?
« Reply #1 on: November 13, 2024, 09:36:21 pm »
First the question in the title: Int does not return an integer value because thats not what it is intended to do if you look at the documentation of the int function: https://www.freepascal.org/docs-html/rtl/system/int.html
Quote
Int returns the integer part of any Real X, as a Real.
What you are looking for is the trunc function: https://www.freepascal.org/docs-html/rtl/system/trunc.html
Quote
Trunc returns the integer part of X, which is always smaller than (or equal to) X in absolute value.

Second the question of the thread: If you look at the documentation of the language: https://www.freepascal.org/docs-html/current/ref/refsu44.html#x151-17500012.8.1
Quote
With the exception of Div and Mod, which accept only integer expressions as operands, all operators accept real and integer expressions as operands.
The reason div is not overloaded for doubles, is very simply because it's the integer division it's an operation thats solely for dividing integers by integers and returning integers.

Lastly to solve your problem:
Code: Pascal  [Select][+][-]
  1.   if (MaxVal mod NumSegments = 0)
  2.     then SegmentVal:=MaxVal div NumSegments
  3.     else SegmentVal:= int(MaxVal/NumSegments);
Assuming MaxVal and NumSegments are both integers, just use:
Code: Pascal  [Select][+][-]
  1. SegmentVal:=MaxVal div NumSegments;
If they are doubles use:
Code: Pascal  [Select][+][-]
  1. SegmentVal:=trunc(MaxVal / NumSegments);

It's very easy if you read the documentation :)

McDoob

  • Newbie
  • Posts: 6
Re: Why doesn't the 'int' function return an integer value?
« Reply #2 on: November 13, 2024, 09:46:28 pm »
Hi, Warfley!
Thanks for the quick response!

If I understand you correctly, I need to RTFM, yes?  8)

But, I don't think trunc will work here. Is there a rounding func, instead? Later on in my program, I use

   PartSegment:=int(((CurVal mod SegmentVal)/SegmentVal)*100);

and I must assume that would be a problem, even after applying your response...
« Last Edit: November 13, 2024, 09:55:20 pm by McDoob »

Warfley

  • Hero Member
  • *****
  • Posts: 1763
Re: Why doesn't the 'int' function return an integer value?
« Reply #3 on: November 13, 2024, 09:54:00 pm »
So trunc just "truncates" the number, so it removes everything behind the decimal point. So 0.2, 0.8 and 0.99 all become 0 while -3.2, -3.7 and -3.99 all become -3.

There is also round which does the "usual" rounding, so 0.3 becomes 0 and 0.7 becomes 1.

McDoob

  • Newbie
  • Posts: 6
Re: Why doesn't the 'int' function return an integer value?
« Reply #4 on: November 13, 2024, 10:02:17 pm »
Clearly, your status as 'Hero Member' is well deserved, sir.

Assuming I actually RTFM, and then apply the round func to my program...

What happens when the variable approaches 0.5? Or 0.05? Or whatever? Does 'round' round down, or round up?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11947
  • FPC developer.
Re: Why doesn't the 'int' function return an integer value?
« Reply #5 on: November 13, 2024, 10:04:02 pm »
Default banker's rounding. So x.5 up when x is even and down when x is odd

McDoob

  • Newbie
  • Posts: 6
Re: Why doesn't the 'int' function return an integer value?
« Reply #6 on: November 13, 2024, 10:10:19 pm »
I've never heard of 'banker's rounding' before this.

I was taught that x.5 is always up...thanks for your help, marcov, and Warfley!

How do I mark this problem as [Solved]?
« Last Edit: November 13, 2024, 10:14:59 pm by McDoob »

Warfley

  • Hero Member
  • *****
  • Posts: 1763
Re: Why doesn't the 'int' function return an integer value?
« Reply #7 on: November 13, 2024, 10:17:30 pm »
It applies round to nearest even, meaning 0.5 is rounded down, because 0 is an even number. 1.5 is rounded up because 2 is an even number. This is generally how the FPU (floating point unit) in your CPU is wired and is basically how all computers do rounding nowadays. It's counter intuitive to what you may have learned in school, but it reduces the average rounding error because if half the time it is rounded up and half the time it is rounded down, on average it evens out.

Example:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses SysUtils;
  6.  
  7. function RoundUp(const d: Double): Integer; inline;
  8. begin
  9.   // This will round down when <.5 and round up for >=.5
  10.   Result := trunc(d+0.5);
  11. end;
  12.  
  13. const
  14.   iter = 10000000;
  15. var
  16.   sum: Double;
  17.   roundedsum: Integer;
  18.   i: Integer;
  19.   rndval: Double;
  20.   start: QWord;
  21. begin
  22.   Randomize;
  23.   sum:=0;
  24.   roundedsum:=0;
  25.   start:=GetTickCount64;
  26.   for i:=1 to iter do
  27.   begin
  28.     // random value between 0 and 10 with 1 decimal digit
  29.     rndval:=Random(100)/10;
  30.     sum+=rndval;
  31.     roundedsum+=round(rndval);
  32.   end;
  33.   WriteLn('Nearest Even time: ', GetTickCount64-start,'ms');
  34.   WriteLn('Nearest Even error: ', (sum-roundedsum).tostring);
  35.   // Now the same for roundup
  36.   sum:=0;
  37.   roundedsum:=0;
  38.   start:=GetTickCount64;
  39.   for i:=1 to iter do
  40.   begin
  41.     // random value between 0 and 10 with 1 decimal digit
  42.     rndval:=Random(100)/10;
  43.     sum+=rndval;
  44.     roundedsum+=roundup(rndval);
  45.   end;
  46.   WriteLn('Round up time: ', GetTickCount64-start,'ms');
  47.   WriteLn('Round up error: ', (sum-roundedsum).tostring);
  48.   ReadLn;
  49. end.
  50.  
Result:
Code: Pascal  [Select][+][-]
  1. Nearest Even time: 93ms
  2. Nearest Even error: -107,90000513196
  3. Round up time: 157ms
  4. Round up error: -498955,69999671
For n operations the rounding error of nearest even rounding is about 0, while for rounding up it is around -n/2 and for rounding down it's around n/2.
And because it directly utilizes the hardware implementation of the FPU it's also much faster
« Last Edit: November 13, 2024, 10:21:26 pm by Warfley »

McDoob

  • Newbie
  • Posts: 6
Re: Why doesn't the 'int' function return an integer value?
« Reply #8 on: November 13, 2024, 10:21:25 pm »
Warfley, thank you for the deeper dive.

I can expect my program to respond better to 'round' than 'int' for sure. Assuming that 'round's output is an integer...

Again, how do I mark this as [Solved]?
« Last Edit: November 13, 2024, 10:38:46 pm by McDoob »

carl_caulkett

  • Hero Member
  • *****
  • Posts: 649
Re: Why doesn't the 'int' function return an integer value?
« Reply #9 on: November 13, 2024, 10:55:52 pm »
Just modify the first message in your thread; as well as the body of the message, you'll also be able to amend the title where you can add [SOLVED] as a prefix or suffix.
"It builds... ship it!"

McDoob

  • Newbie
  • Posts: 6
Re: Why doesn't the 'int' function return an integer value?
« Reply #10 on: November 13, 2024, 11:23:38 pm »
Just modify the first message in your thread; as well as the body of the message, you'll also be able to amend the title where you can add [SOLVED] as a prefix or suffix.

thx..if it builds, it ships. XD

If not FUBAR
  then SNAFU;
end.
« Last Edit: November 13, 2024, 11:36:54 pm by McDoob »

jollytall

  • Sr. Member
  • ****
  • Posts: 366
Re: [SOLVED] Why doesn't the 'int' function return an integer value?
« Reply #11 on: November 14, 2024, 01:26:38 pm »
What I do is
Code: Pascal  [Select][+][-]
  1. i := round(int(r));
round alone is not the same because of rounding up for r> or >=0.5.
trunc is not good because of negative numbers.
So, if you want an int() function that gives back an integer, AFAIK the best is the above. You can make it a function or a macro if you prefer.
« Last Edit: November 14, 2024, 04:19:27 pm by jollytall »

tetrastes

  • Hero Member
  • *****
  • Posts: 600
Re: [SOLVED] Why doesn't the 'int' function return an integer value?
« Reply #12 on: November 14, 2024, 02:07:17 pm »
What I do is
Code: Pascal  [Select][+][-]
  1. i := round(int(r));
...
trunc is not good because of negative numbers.

What do you mean?
Your code produces the same as
Code: Pascal  [Select][+][-]
  1. i := trunc(r);


tetrastes

  • Hero Member
  • *****
  • Posts: 600
Re: Why doesn't the 'int' function return an integer value?
« Reply #13 on: November 14, 2024, 02:28:46 pm »
Code: Pascal  [Select][+][-]
  1.   iter = 10000000;
Result:
Code: Pascal  [Select][+][-]
  1. Round up error: -498955,69999671
For n operations the rounding error of nearest even rounding is about 0, while for rounding up it is around -n/2 and for rounding down it's around n/2.

n(iter) is 107, so ~n/20  ;)

jollytall

  • Sr. Member
  • ****
  • Posts: 366
Re: [SOLVED] Why doesn't the 'int' function return an integer value?
« Reply #14 on: November 14, 2024, 04:18:36 pm »
What do you mean?

Mixed up... I don't know why it came to my head. I even looked in some of my code now, and did not find when I used this or something similar. Suddenly I felt that int() is rounding toward negative infinity (in which case I could use floor()). So, I am not sure why it got stuck in my memory.
Post crossed out.

 

TinyPortal © 2005-2018