n-fix(n)

General FreeBASIC programming questions.
owen
Posts: 555
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

n-fix(n)

Post by owen »

'i wish this would work.
'Function mymod(n As Double,m As Integer) As Double
' Return Fix(n) Mod m + n - Fix(n)
'End Function

Code: Select all

Declare Function mymod(n As Double,m As Integer) As Double

Dim As Double n
Dim As Integer m

n=54.321
m=10
Print mymod(n,m)
Sleep
End

'i wish this would work
'Function mymod(n As Double,m As Integer) As Double
'	Return Fix(n) Mod m + n - Fix(n)
'End Function

'my really bad solution
Function mymod(n As Double,m As Integer) As Double
	Select Case n
		Case 0
			mymod = 0
		Case CDbl(m)
			mymod = CDbl(m)
		Case Else
			If InStr(Str(n),"e")<>0 Then
				mymod=0
			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 If
	End Select
End Function
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: n-fix(n)

Post by dafhi »

return n - m*int(n/m)
owen
Posts: 555
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: n-fix(n)

Post by owen »

@ dafhi
i get
4.320999999999998
xlucas
Posts: 334
Joined: May 09, 2014 21:19
Location: Argentina

Re: n-fix(n)

Post by xlucas »

Owen... why do you want a floating point function to return a modulus? The remainder of a division is an integer concept. When talking about non-integers, it's very rare to refer to the remainder or modulus. When working with integers, you have:

n \ m = Int(n / m) 'Integer division

Therefore, it makes sense to obtain the remainder as Dafhi said:

remainder = n - m * Int(n / m)

Because you first do an integer divide, which destroys the remainder data. Then you multiply again to scale the number to the same value without the remainder. Finally, you substract this from the original number. What you get is the remainder. Of course, if you do this to a floating point (real) n, your "remainder" will in general be real too, not an integer. So what you're obtaining is what I would expect.
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: n-fix(n)

Post by deltarho[1859] »

Because n - Fix(n) => 0.320999999999998 when it should be 54.321 - 54 => 0.321

54.321 is converted to binary - cannot be done exactly. If FreeBASIC had extended precision using all of the 80 bits of the FPU then that would help but we could end up with just more '9s'.
owen
Posts: 555
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: n-fix(n)

Post by owen »

@ xlucas
i need the decimal portion of the mod because i use the result in calculations for my cad project such as when i rotate 364.123 i use the result of 4.123 in my dxf files (representation of the drawing)

any how mymod function works using string manipulation

just wanted to ask why fix wouldn't work
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: n-fix(n)

Post by deltarho[1859] »

Fix is working.

The most accurate representation of 54.321 in double precision is 54.3209999999999979536369210109

"." + Mid(Str(n),InStr(Str(n),".")+1) is not using the Floating Point Unit.
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: n-fix(n)

Post by dafhi »

Maybe you want the output looking nice for printing?

i use this a lot

Code: Select all

function round(in as single, places as ubyte = 2) as string
  dim as integer mul = 10 ^ places
  return str(csng(int(in * mul + .5) / mul))
End Function

? round(mymod(n, m))
thesanman112
Posts: 538
Joined: Jul 15, 2005 4:13

Re: n-fix(n)

Post by thesanman112 »

Owen,

maybe the frac function is what you are looking for??? there is also a function to round to the nearest decimal specified, i just dont recall what it is.

like print using ###.####??

there is also a function called FORMAT, im just reading up on it, but it looks like it may do what you need as well.
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: n-fix(n)

Post by deltarho[1859] »

Fix( n ) = n - Frac( n ) so n - Fix( n ) = Frac( n )

Frac(54.321) => 0.320999999999998
xlucas
Posts: 334
Joined: May 09, 2014 21:19
Location: Argentina

Re: n-fix(n)

Post by xlucas »

Oh! I see then... If that is what you need, then yes, you could just manipulate the numbers manually as string or use your own data type. I think for these purposes, it could be better to represent the non integral part as a fraction instead of a mantissa. So, say you input the value 55.25. This number has a limited number of digits in decimal, but is periodic in binary. Now, if you represent it as 55 + 1/4, the base no longer matters. You could use something like this:

Code: Select all

Type Mixed
   i As Long  'Integral part
   n As UShort  'Numerator of non-integral part
   d As UShort  'Denominator of non-integral part
End Type
And build your own operators. The processing would be faster than with string manipulation, I think. Yet, unless you need to make an enormous number of calculations in a short time, you won't notice the difference.
thesanman112
Posts: 538
Joined: Jul 15, 2005 4:13

Re: n-fix(n)

Post by thesanman112 »

deltarho[1859] wrote:Fix( n ) = n - Frac( n ) so n - Fix( n ) = Frac( n )

Frac(54.321) => 0.320999999999998
Dont think so.....
thesanman112
Posts: 538
Joined: Jul 15, 2005 4:13

Re: n-fix(n)

Post by thesanman112 »

there are so many easy ways to fix this....
Depending on what you are going to do with results,
If its just to display the print using will do...
If it needs to recalculate then just use the format function.
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: n-fix(n)

Post by deltarho[1859] »

Using and Format is a good way for printing purposes but here is one way to 'overcome' the truncation involved when the Floating Point Unit comes into play.

The result is rounded to a requested number of decimal places.

Code: Select all

Function mymod( n As Double, m As Integer, DecPlaces as Ubyte ) As Double
   Return Fix( n ) Mod m + Fix( Frac( n )*10^DecPlaces + 0.5)/10^DecPlaces
End Function

Dim As Double n
Dim As Integer m
Dim DecPlaces As Ubyte

n = 54.321
m = 10
DecPlaces = 3

Print mymod( n, m, 3 )

n = 85.987654321
m = 10
DecPlaces = 4

Print mymod( n, m, 4 )

Sleep
which gives

4.321
5.9877

Added: In this case I reckon that 'Int' is better than 'Fix'.
owen
Posts: 555
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: n-fix(n)

Post by owen »

deltarho[1859] that works great as long as DecPlaces does not exceed the number of DecPlaces in the number.
thanks

next question would be:
how to figure out how many DecPlaces are in the number.
Post Reply