I need the opposite of int...
I need to get the fraction part of a number, like everything after the decimal point.
For example.
Given 5.123
It returns ".123"
Is there a function that does that already? I am looking in the help file.
I hacked a function together that uses mod, but its not the best.
fractional=((number*1000) MOD 1000)/1000
As well, floor and ceiling would be great as well.
Return the Fractional part of a number

 Posts: 306
 Joined: Jun 02, 2005 7:11
 Contact:
FRAC does that.
displays 0.123
http://www.freebasic.net/wiki/wikka.php?wakka=KeyPgFrac
For the other functions:
where i is between 0 and 0.999 inclusive, returns the floor and add 1 to get the ceiling.
http://www.freebasic.net/wiki/wikka.php?wakka=KeyPgInt
Code: Select all
print frac(5.123)
displays 0.123
http://www.freebasic.net/wiki/wikka.php?wakka=KeyPgFrac
For the other functions:
Code: Select all
Int(i)
where i is between 0 and 0.999 inclusive, returns the floor and add 1 to get the ceiling.
http://www.freebasic.net/wiki/wikka.php?wakka=KeyPgInt
Last edited by RayBritton on Sep 17, 2009 13:07, edited 3 times in total.

 Site Admin
 Posts: 6221
 Joined: Jul 05, 2005 17:32
 Location: Manchester, Lancs
It should be noted that frac() is the counterpart of fix()  i.e. frac(x) = x  fix(x). Because fix() truncates rather than rounds down, this results in nonpositive results for negative numbers.
If you want the result always to be nonnegative, you should explicitly do "x  int(x)" instead. (int() always rounds down, so obviously the difference can never be negative.)
To get the ceiling, you should do "int(x)". Don't just add 1 to int() because that will mean whole numbers get rounded up  e.g. int(3) + 1 = 4.
If you want the result always to be nonnegative, you should explicitly do "x  int(x)" instead. (int() always rounds down, so obviously the difference can never be negative.)
To get the ceiling, you should do "int(x)". Don't just add 1 to int() because that will mean whole numbers get rounded up  e.g. int(3) + 1 = 4.
mymod
n mod m : the result is an integer
n mod m + frac(n): using FRAC returns an incorrect result
mymod(n,m): seems to work correctly
365.01 Mod 360 = 5
365.01 Mod 360 = 5.009999999999991
365.01 Mod 360 = 5.01
n mod m + frac(n): using FRAC returns an incorrect result
mymod(n,m): seems to work correctly
365.01 Mod 360 = 5
365.01 Mod 360 = 5.009999999999991
365.01 Mod 360 = 5.01
Code: Select all
'$lang: "deprecated"
Declare Function mymod(n As Double,m As Integer) As Double
Function mymod(n As Double,m As Integer) As Double
Select Case n
Case 0
mymod = 0
Case Else
If Instr(Str(n),".")<>0 Then
mymod=Val(Str(n Mod m)+"."+Mid(Str(n),Instr(Str(n),".")+1))
Else
mymod = (n Mod m)
EndIf
End Select
End Function
Dim As Double n
Dim As Integer m
n=365.01
m=360
Print n;" Mod";m;" ="; n Mod m
Print n;" Mod";m;" ="; n Mod m + Frac(n)
Print n;" Mod";m;" ="; mymod(n,m)
Sleep
End
' 365.01 Mod 360 = 5
' 365.01 Mod 360 = 5.009999999999991
' 365.01 Mod 360 = 5.01
oops forgot about mod rounding
298.7967216637024 mod 360 is 299 because 298.7xx is rounded up
so naturally mymod function (above post) didn't work.
this is better
so naturally mymod function (above post) didn't work.
this is better
Code: Select all
Function mymod(n As Double,m As Integer) As Double
Select Case n
Case 0
mymod = 0
Case Else
If InStr(Str(n),".")<>0 Then
mymod=Val(Str(val(Mid(Str(n),1,InStr(Str(n),".")1)) Mod m)+"."+Mid(Str(n),InStr(Str(n),".")+1))
Else
mymod = (n Mod m)
EndIf
End Select
End Function

 Site Admin
 Posts: 6221
 Joined: Jul 05, 2005 17:32
 Location: Manchester, Lancs
Re: mymod
That's as correct as floatingpoint can get.owen wrote:n mod m : the result is an integer
n mod m + frac(n): using FRAC returns an incorrect result
Powers of 1/10 cannot be stored accurately in binary, just as powers of 1/3 cant be stored in decimal. For example:
1/300 is 0.0033333 in decimal with 5 digits precision.
1 + 1/300 is 1.0033 in the same format.
If you take 1 away from that you get 0.0033000.
So it looks like the math was wrong, but the math was actually accurate. It's just that it was working on a number that wasn't exactly what you want it to be.
In your trick, str() is giving you the imprecise number .009999..., but to fewer places (because the part before the decimal point takes up more of the significant digits), so it looks accurate. When you pass it back to val(), it fudges the end digits so the final decimal looks as close as it can to .01.
Usually the binary digits can be fudged enough with val() so that the decimal expansion looks like the decimal number you want, but it's not always guaranteed, e.g.
Code: Select all
dim i as integer, s as string
for i = 0 to 100
s = "1e" & i
print s, val(s)
next
using variable as double
thanx for the post
if my goal is to get a result of 5.0 to 5.9 into the variable called result what's my best choice?
the results range from 5.0 to 6.8
if my goal is to get a result of 5.0 to 5.9 into the variable called result what's my best choice?
Code: Select all
Dim As Double n,result
Dim As Integer m
m=360
For n = 365.0 To 365.9 Step .1
result = n Mod m + Frac(n)
Print result
Next
Sleep
End
the results range from 5.0 to 6.8

 Site Admin
 Posts: 6221
 Joined: Jul 05, 2005 17:32
 Location: Manchester, Lancs
One solution might be to use integer math and store everything as tenths of degrees. So a full circle would be 3600.
To ensure it prints correctly without using Print Using or Format you'll probably want to use Str() on the integer and manually insert the decimal point.
I've just checked, and Print simply won't print some double precision values the way you'd want it to, so you can't just print the result of the number divided by 10:
Early weak points seem to be values over 8 and values over 64, which last until the number gains an extra decimal digit and the loss of precision falls off the end.
To ensure it prints correctly without using Print Using or Format you'll probably want to use Str() on the integer and manually insert the decimal point.
Code: Select all
dim i as integer, s as string
for i = 0 to 99
s = str(i)
s = left(s, len(i)1) & "." & right(s, 1)
if left(s, 1) = "." then s = "0" & s
print s
next
I've just checked, and Print simply won't print some double precision values the way you'd want it to, so you can't just print the result of the number divided by 10:
Code: Select all
dim i as integer, s as string
for i = 0 to 999
s = str(i / 10#)
if instr(s & ".", ".") + 1 < len(s) then print s
next
Who is online
Users browsing this forum: No registered users and 5 guests