Always for me a Big question
-
- Posts: 49
- Joined: Dec 16, 2011 3:48
Always for me a Big question
With all the progresses in computer science and in year 2017 why programs can keep only 20-digit numbers(ulongint) and if I want to compute long and big numbers there is a limitation in it? In freebasic we can have a string about 2G it is good ,but with numbers......? I want to work with big numbers about for example 500 digits and can I have a digit unit other than binary or decade with ascci codes(base 256 ) and how ?
Thank you in advance.
Thank you in advance.
Last edited by student1347 on May 05, 2017 11:53, edited 1 time in total.
Re: Always for me a Big question
There are libraries for that very purpose (I am not aware of any language, having such *native*).
See: Section Library's of the Forum ...
See: Section Library's of the Forum ...
Re: Always for me a Big question
get the gmp library.
gmp 6.1.2
from srvaldez (top post)
http://www.freebasic.net/forum/viewtopi ... 55#p230255
Put the static library (.a) into your lib folder.
That's all.
Try this factorial.
gmp 6.1.2
from srvaldez (top post)
http://www.freebasic.net/forum/viewtopi ... 55#p230255
Put the static library (.a) into your lib folder.
That's all.
Try this factorial.
Code: Select all
#Include Once "gmp.bi"
Function factorial(n As Ulong,numberbase as long=10) As String
Dim As __mpz_struct Intanswer
mpz_init( @Intanswer)
mpz_fac_ui(@Intanswer,n)
Dim As ZString Ptr s = mpz_get_str(0, numberbase, @intanswer)
mpz_clear(@Intanswer)
function= Trim(*s)
deallocate(s)
End Function
print factorial(150,16)
print
print factorial(150,10)
sleep
Re: Always for me a Big question
hello student1347
you may also be interested in the "Big Number Wrapper" (using GMP int) by Yetifoot http://www.freebasic.net/forum/viewtopic.php?t=7173
example code by Yetifoot
you may also be interested in the "Big Number Wrapper" (using GMP int) by Yetifoot http://www.freebasic.net/forum/viewtopic.php?t=7173
example code by Yetifoot
Code: Select all
#include "gmp_int.bi"
' Powers of two
print "Some powers of two"
for i as integer = 0 to 128
print "2 ^ " & i & " = " & gmp_int(2) ^ gmp_int(i)
next i
' Big numbers in FOR
print "Big numbers in FOR loop"
for i as gmp_int = gmp_int("10000000000000000") to gmp_int("50000000000000000") step gmp_int("20000000000000000")
print i
next i
' Printing a big number using a non 10 number base.
dim n as gmp_int = gmp_int("123456789123456789123456789123456789")
print "Printing a big number in base 16"
print n, n.getString( 16 )
Re: Always for me a Big question
Python (2.7) seems to do this fine:I am not aware of any language, having such *native*
Code: Select all
a = 123456789123456789123456789123456789123456789123456789
b = 987654321987654321987654321987654321987654321987654321
c = a + b + 1
print c
This however, may not be so great:
Code: Select all
a = 123456789123456789123456789123456789123456789123456789.1
b = 987654321987654321987654321987654321987654321987654321
c = a + b + 1
print c
-
- Posts: 231
- Joined: Apr 10, 2010 11:41
- Location: Japan
- Contact:
Re: Always for me a Big question
Dear srvaldez
I am interested in the "Big Number Wrapper" (using GMP int) by Yetifoot http://www.freebasic.net/forum/viewtopic.php?t=7173 .
Unfortunately the "example code" shows a following error:
BigNumberWrapper.bas(19) error 197: Missing overloaded operator: next (with step), before 'i' in 'Next i'
Please teach me if there is a countermeasure method.
I am interested in the "Big Number Wrapper" (using GMP int) by Yetifoot http://www.freebasic.net/forum/viewtopic.php?t=7173 .
Unfortunately the "example code" shows a following error:
BigNumberWrapper.bas(19) error 197: Missing overloaded operator: next (with step), before 'i' in 'Next i'
Please teach me if there is a countermeasure method.
Re: Always for me a Big question
hello Makoto WATANABE
I made some changes, hope it helps.
gmp_int.bi
test.bas
I made some changes, hope it helps.
gmp_int.bi
Code: Select all
#ifndef __GMP_INT_BI__
#define __GMP_INT_BI__
#include "gmp.bi"
type gmp_int
declare constructor ( )
declare constructor ( byval i as integer )
declare constructor ( byref s as string )
declare constructor ( byref g as gmp_int )
declare destructor ( )
declare operator let ( byref g as gmp_int )
declare operator let ( byval i as Integer )
declare operator let ( byref s as string )
declare operator cast ( ) as Integer
declare operator cast ( ) as string
' For Next Implicit step = +1
Declare Operator For ( )
Declare Operator Step( )
declare operator for ( byref stp as gmp_int )
declare operator step ( byref stp as gmp_int )
declare operator next ( byref end_cond as gmp_int ) as integer
Declare Operator Next( Byref end_cond As gmp_int, Byref step_var As gmp_int ) As Integer
declare function getString ( byval _base as integer = 10 ) as string
num as mpz_ptr = 0
end type
declare operator + ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator - ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator * ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator \ ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator / ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator ^ ( byref lhs as gmp_int, byval rhs as gmp_int ) as gmp_int
declare operator mod ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator and ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator or ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator xor ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
declare operator - ( byref rhs as gmp_int ) as gmp_int
declare operator not ( byref rhs as gmp_int ) as gmp_int
declare operator = ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator < ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator > ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator <= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator >= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
declare operator <> ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
#endif '__GMP_INT_BI__
''''#include "gmp_int.bi" 'code above
' Any time we allocate with sizeof( __mpz_struct ), we add the safety net onto the size,
' without this it crashes for me, perhaps the __mpz_struct is declared wrong in gmp.bi,
' whatever the reason it doesn't matter too much, as the struct is only manipulated by
' the gmp functions.
const SAFETY_NET = 20
'::::::::
constructor gmp_int ( )
num = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
mpz_init_set_si( num, 0 )
end constructor
'::::::::
constructor gmp_int ( byval i as integer )
num = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
mpz_init_set_si( num, i )
end constructor
'::::::::
constructor gmp_int ( byref s as string )
num = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
mpz_init_set_str( num, strptr( s ), 10 )
end constructor
'::::::::
constructor gmp_int ( byref g as gmp_int )
num = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
mpz_init_set( num, g.num )
end constructor
'::::::::
destructor gmp_int ( )
mpz_clear( num )
deallocate( num )
end destructor
'::::::::
operator gmp_int.let ( byref g as gmp_int )
mpz_set( num, g.num )
end operator
'::::::::
operator gmp_int.let ( byval i as Integer )
mpz_set_si( num, i )
end operator
'::::::::
operator gmp_int.let ( byref s as string )
mpz_set_str( num, strptr(s), 10 )
end operator
Operator gmp_int.cast ( ) As Integer
Operator = mpz_get_si(num)
End Operator
'::::::::
operator gmp_int.cast ( ) as string
operator = getString( 10 )
end operator
'=====================================================================
' Implicit step gmp_int.For gmp_int.Next gmp_int.Step is +1
Operator gmp_int.for ( )
End Operator
Operator gmp_int.step ( )
this += 1 'this = this+1 '
End Operator
Operator gmp_int.next ( Byref end_cond As gmp_int ) As Integer
Return this <= end_cond
End Operator
'' explicit step versions
''
Operator gmp_int.for ( Byref step_var As gmp_int )
End Operator
Operator gmp_int.step ( Byref step_var As gmp_int )
this += step_var 'this = this + step_var '
End Operator
Operator gmp_int.next ( Byref end_cond As gmp_int, Byref step_var As gmp_int ) As Integer
If step_var < 0 Then
Return this >= end_cond
Else
Return this <= end_cond
End If
End Operator
'::::::::
function gmp_int.getString ( byval _base as integer = 10 ) as string
dim as zstring ptr s = mpz_get_str( 0, _base, num )
if s then
function = *s
deallocate( s )
end if
end function
'::::::::
operator + ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_add( result.num, lhs.num, rhs.num )
operator = result
end operator
'::::::::
operator - ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_sub( result.num, lhs.num, rhs.num )
operator = result
end operator
'::::::::
operator * ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_mul( result.num, lhs.num, rhs.num )
operator = result
end operator
'::::::::
operator \ ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_tdiv_q( result.num, lhs.num, rhs.num )
operator = result
end operator
'::::::::
operator / ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
' This really is quite nasty, but it's the best way I could come up with
' to do an FP divide, while rounding results the way people may expect them.
' 0.5 becomes 1, 0.4 becomes 0, -0.5 becomes -1, -0.4 becomes 0
' I'm not 100% that temp is needed, but I used it just to be safe, for some
' GMP functions it seems a bad idea to pass an mpz as dest and one of the sources.
dim as mpf_ptr l, r, q, half, temp
dim as integer cmp_val
dim as gmp_int result
l = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
r = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
q = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
half = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
temp = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
mpf_init( l )
mpf_init( r )
mpf_init( q )
mpf_init_set_str( half, "0.50", 10 )
mpf_init( temp )
mpf_set_z( l, lhs.num )
mpf_set_z( r, rhs.num )
mpf_div( q, l, r )
cmp_val = mpf_cmp_d( q, 0 )
if cmp_val > 0 then
mpf_add( temp, q, half )
elseif cmp_val < 0 then
mpf_sub( temp, q, half )
else
mpf_set( temp, q )
end if
mpf_trunc( q, temp )
mpz_set_f( result.num, q )
mpf_clear( l )
mpf_clear( r )
mpf_clear( q )
mpf_clear( half )
mpf_clear( temp )
deallocate( l )
deallocate( r )
deallocate( q )
deallocate( half )
deallocate( temp )
operator = result
end operator
'::::::::
operator ^ ( byref lhs as gmp_int, byval rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_pow_ui( result.num, lhs.num, mpz_get_ui( rhs.num ) )
operator = result
end operator
'::::::::
operator mod ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_mod( result.num, lhs.num, rhs.num )
operator = result
end operator
'::::::::
operator and ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_and( result.num, lhs.num, rhs.num )
operator = result
end operator
'::::::::
operator or ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_ior( result.num, lhs.num, rhs.num )
operator = result
end operator
'::::::::
operator xor ( byref lhs as gmp_int, byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_xor( result.num, lhs.num, rhs.num )
operator = result
end operator
'::::::::
operator - ( byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_neg( result.num, rhs.num )
operator = result
end operator
'::::::::
operator not ( byref rhs as gmp_int ) as gmp_int
dim as gmp_int result
mpz_com( result.num, rhs.num )
operator = result
end operator
'::::::::
operator = ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
operator = (mpz_cmp( lhs.num, rhs.num ) = 0)
end operator
'::::::::
operator < ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
operator = (mpz_cmp( lhs.num, rhs.num ) < 0)
end operator
'::::::::
operator > ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
operator = (mpz_cmp( lhs.num, rhs.num ) > 0)
end operator
'::::::::
operator <= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
operator = (mpz_cmp( lhs.num, rhs.num ) <= 0)
end operator
'::::::::
operator >= ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
operator = (mpz_cmp( lhs.num, rhs.num ) >= 0)
end operator
'::::::::
operator <> ( byref lhs as gmp_int, byref rhs as gmp_int ) as integer
operator = (mpz_cmp( lhs.num, rhs.num ) <> 0)
end operator
Code: Select all
#include "gmp_int.bi"
dim as gmp_int i, two = 2 'if the number is small
' if the number is larger than FB integer then use: two = gmp_int("2")
dim as integer k
' Powers of two
print "Some powers of two"
for i = 0 to 128
print "2 ^ " & i & " = " & two ^ i
next i
print
print "casting a gmp_int to a FreeBASIC Integer"
print "this should only be done if you know the gmp_int will fit in a Integer"
k = two
print "k = two ->";k
Re: Always for me a Big question
Gmp_int.bi has two problems in the floating point division (/) routine. First the gmp floats need a 16 byte structure (__mpf_struct) but they get a 12 byte structure (__mpz_struct) which result in data stored outside the structure and most likely overwriting data in the next structure, hence crashes.
Solution: change __mpz_struct to __mpf_struct.
The size for gmp_floats is fixed where as the size for integers depends on the size of the number. The default size for floats is 32bit.
Solution: find the size in bits of lhs and rhs. Take the biggest of the two. Use mpf_init2 instead of mpf_init to give the floats a size that is at least equal to the size of the integers
Tweaked the Constructor ( ByRef s As String) to Constructor ( ByRef s As String, ByVal _base As Long = 10 ) to make it possible to enter numbers in base 2 to 62. Default = 10 (decimal)
i = gmp_int("1234") = gmp_int("1234", 10)
i = gmp_int("abcd", 16) ' hexadecimal
i = gmp_int("1001", 2) ' binary
i = gmp_int("7777", 8) ' octal
gmp_int.bi
littletest.bas
Solution: change __mpz_struct to __mpf_struct.
The size for gmp_floats is fixed where as the size for integers depends on the size of the number. The default size for floats is 32bit.
Solution: find the size in bits of lhs and rhs. Take the biggest of the two. Use mpf_init2 instead of mpf_init to give the floats a size that is at least equal to the size of the integers
Tweaked the Constructor ( ByRef s As String) to Constructor ( ByRef s As String, ByVal _base As Long = 10 ) to make it possible to enter numbers in base 2 to 62. Default = 10 (decimal)
i = gmp_int("1234") = gmp_int("1234", 10)
i = gmp_int("abcd", 16) ' hexadecimal
i = gmp_int("1001", 2) ' binary
i = gmp_int("7777", 8) ' octal
gmp_int.bi
Code: Select all
#Ifndef __GMP_INT_BI__
#Define __GMP_INT_BI__
#Include Once "gmp.bi"
Type gmp_int
Declare Constructor ( )
Declare Constructor ( ByVal i As Integer )
Declare Constructor ( ByRef s As String, ByVal _base As Long = 10 )
Declare Constructor ( ByRef g As gmp_int )
Declare Destructor ( )
Declare Operator Let ( ByRef g As gmp_int )
Declare Operator Let ( ByVal i As Integer )
Declare Operator Let ( ByRef s As String )
Declare Operator Cast ( ) As Integer
Declare Operator Cast ( ) As String
' For Next Implicit step = +1
Declare Operator For ( )
Declare Operator Step( )
Declare Operator For ( ByRef stp As gmp_int )
Declare Operator Step ( ByRef stp As gmp_int )
Declare Operator Next ( ByRef end_cond As gmp_int ) As Integer
Declare Operator Next( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer
Declare Function getString ( ByVal _base As Integer = 10 ) As String
num As mpz_ptr = 0
End Type
Declare Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As gmp_int ) As gmp_int
Declare Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator - ( ByRef rhs As gmp_int ) As gmp_int
Declare Operator Not ( ByRef rhs As gmp_int ) As gmp_int
Declare Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
#EndIf '__GMP_INT_BI__
''''#include "gmp_int.bi" 'code above
' Any time we allocate with sizeof( __mpz_struct ), we add the safety net onto the size,
' without this it crashes for me, perhaps the __mpz_struct is declared wrong in gmp.bi,
' whatever the reason it doesn't matter too much, as the struct is only manipulated by
' the gmp functions.
' Const SAFETY_NET = 20
Const SAFETY_NET = 0 ' not needed
'::::::::
Constructor gmp_int ( )
num = Callocate( SizeOf( __mpz_struct ) + SAFETY_NET )
' mpz_init_set_si( num, 0 )
mpz_init( num )
End Constructor
'::::::::
Constructor gmp_int ( ByVal i As Integer )
num = Callocate( SizeOf( __mpz_struct ) + SAFETY_NET )
mpz_init_set_si( num, i )
End Constructor
'::::::::
Constructor gmp_int ( ByRef s As String, ByVal _base As Long = 10 )
num = Callocate( SizeOf( __mpz_struct ) + SAFETY_NET )
mpz_init_set_str( num, StrPtr( s ), _base )
End Constructor
'::::::::
Constructor gmp_int ( ByRef g As gmp_int )
num = Callocate( SizeOf( __mpz_struct ) + SAFETY_NET )
mpz_init_set( num, g.num )
End Constructor
'::::::::
Destructor gmp_int ( )
mpz_clear( num )
DeAllocate( num )
End Destructor
'::::::::
Operator gmp_int.let ( ByRef g As gmp_int )
mpz_set( num, g.num )
End Operator
'::::::::
Operator gmp_int.let ( ByVal i As Integer )
mpz_set_si( num, i )
End Operator
'::::::::
Operator gmp_int.let ( ByRef s As String )
mpz_set_str( num, StrPtr(s), 10 )
End Operator
Operator gmp_int.cast ( ) As Integer
Operator = mpz_get_si(num)
End Operator
'::::::::
Operator gmp_int.cast ( ) As String
Operator = getString( 10 )
End Operator
'=====================================================================
' Implicit step gmp_int.For gmp_int.Next gmp_int.Step is +1
Operator gmp_int.for ( )
End Operator
Operator gmp_int.step ( )
This += 1 'this = this+1 '
End Operator
Operator gmp_int.next ( ByRef end_cond As gmp_int ) As Integer
Return This <= end_cond
End Operator
'' explicit step versions
''
Operator gmp_int.for ( ByRef step_var As gmp_int )
End Operator
Operator gmp_int.step ( ByRef step_var As gmp_int )
This += step_var 'this = this + step_var '
End Operator
Operator gmp_int.next ( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer
If step_var < 0 Then
Return This >= end_cond
Else
Return This <= end_cond
End If
End Operator
'::::::::
Function gmp_int.getString ( ByVal _base As Integer = 10 ) As String
Dim As ZString Ptr s = mpz_get_str( 0, _base, num )
If s Then
Function = *s
DeAllocate( s )
End If
End Function
'::::::::
Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_add( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_sub( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_mul( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_tdiv_q( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
' This really is quite nasty, but it's the best way I could come up with
' to do an FP divide, while rounding results the way people may expect them.
' 0.5 becomes 1, 0.4 becomes 0, -0.5 becomes -1, -0.4 becomes 0
' I'm not 100% that temp is needed, but I used it just to be safe, for some
' GMP functions it seems a bad idea to pass an mpz as dest and one of the sources.
Dim As mpf_ptr l, r, q, half, temp
Dim As gmp_int result
' size for gmp floats is fixed, this could lead to loss of precision
' the size is set by mpf_set_default_prec or by using mpf_init2( 'var', size)
' find the size of lhs and rhs, take the longest size and add 32 bit (9 digits)
Dim As ULong l1 = mpz_sizeinbase ( lhs.num , 2)
Dim As ULong r1 = mpz_sizeinbase ( rhs.num , 2)
If r1 > l1 Then l1 = r1
l1 = l1 +32
' l = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
' r = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
' q = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
' half = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
' temp = callocate( sizeof( __mpz_struct ) + SAFETY_NET )
' sizeof( __mpz_struct ) = 12, sizeof( __mpf_struct ) = 16
l = Callocate( SizeOf( __mpf_struct ) )
r = Callocate( SizeOf( __mpf_struct ) )
q = Callocate( SizeOf( __mpf_struct ) )
half = Callocate( SizeOf( __mpf_struct ) )
temp = Callocate( SizeOf( __mpf_struct ) )
mpf_init2( l, l1 ) ' set the size for l to l1
mpf_init2( r, l1 ) ' set the size for l to l1
mpf_init2( q, l1 ) ' set the size for l to l1
mpf_init_set_d( half, .5 )
mpf_init2( temp, l1 ) ' set the size for l to l1
mpf_set_z( l, lhs.num )
mpf_set_z( r, rhs.num )
mpf_div( q, l, r )
Dim As Long cmp_val = mpf_cmp_d( q, 0 )
If cmp_val > 0 Then
mpf_add( temp, q, half )
ElseIf cmp_val < 0 Then
mpf_sub( temp, q, half )
Else
mpf_set( temp, q )
End If
' mpf_trunc( q, temp )
' mpz_set_f( result.num, q )
' mpz_set_d, mpz_set_q and mpz_set_f truncate 'op' to make it an integer.
mpz_set_f( result.num, temp)
mpf_clear( l )
mpf_clear( r )
mpf_clear( q )
mpf_clear( half )
mpf_clear( temp )
DeAllocate( l )
DeAllocate( r )
DeAllocate( q )
DeAllocate( half )
DeAllocate( temp )
Operator = result
End Operator
'::::::::
Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_pow_ui( result.num, lhs.num, mpz_get_ui( rhs.num ) )
Operator = result
End Operator
'::::::::
Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_mod( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_and( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_ior( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_xor( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator - ( ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_neg( result.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator Not ( ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_com( result.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) = 0)
End Operator
'::::::::
Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) < 0)
End Operator
'::::::::
Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) > 0)
End Operator
'::::::::
Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) <= 0)
End Operator
'::::::::
Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) >= 0)
End Operator
'::::::::
Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) <> 0)
End Operator
Code: Select all
#Include Once "gmp_int.bi"
Dim As gmp_int i
Print
Print gmp_int ("1"+String(40, "0")) / gmp_int(3)
Print
i = gmp_int(String(32,"F"), 16)
Print i
i = gmp_int(String(32,"f"), 16)
Print i
i = gmp_int(string(128,"1"), 2)
Print i
Sleep
Last edited by frisian on May 06, 2017 8:56, edited 1 time in total.
Re: Always for me a Big question
thanks frisian
this was Yetifoot's code and I did not check for correctness other than fixing the for loop code, thanks for the fix. :-)
[edit] in the test code, next to last line you missed a right parenthesis
i = gmp_int(string(128,"1", 2) should be i = gmp_int(string(128,"1"), 2) also you missed a print i
this was Yetifoot's code and I did not check for correctness other than fixing the for loop code, thanks for the fix. :-)
[edit] in the test code, next to last line you missed a right parenthesis
i = gmp_int(string(128,"1", 2) should be i = gmp_int(string(128,"1"), 2) also you missed a print i
Re: Always for me a Big question
fixed the code in my previous post, thanks.srvaldez wrote: [edit] in the test code, next to last line you missed a right parenthesis
i = gmp_int(string(128,"1", 2) should be i = gmp_int(string(128,"1"), 2) also you missed a print i
I have cleaned the listing of gmp_int.bi and added shl and shr also added a function to convert a big int into base 2 to 62 string.
gmp_int.bi
Code: Select all
' Original by yetifoot http://www.freebasic.net/forum/viewtopic.php?t=7173
' May 2017: srvaldez
' fixed the loop code
' May 2017: frisian
' corrected and improved the floating point division (/), this makes SAFETY_NET obsolete
' added operators Shr and Shl
' corrected some errors in comments i made, cleaned the listing
' added function gmp_int_2_base that returns a string of a gmp_int number in base 2 to 62 (default 10, decimal)
#Ifndef __GMP_INT_BI__
#Define __GMP_INT_BI__
#Include Once "gmp.bi"
Type gmp_int
Declare Constructor ( )
Declare Constructor ( ByVal i As Integer )
Declare Constructor ( ByRef s As String, ByVal _base As Integer = 10 )
Declare Constructor ( ByRef g As gmp_int )
Declare Destructor ( )
Declare Operator Let ( ByRef g As gmp_int )
Declare Operator Let ( ByVal i As Integer )
Declare Operator Let ( ByRef s As String )
Declare Operator Cast ( ) As Integer
Declare Operator Cast ( ) As String
' For Next Implicit step = +1
Declare Operator For ( )
Declare Operator Step( )
Declare Operator For ( ByRef stp As gmp_int )
Declare Operator Step ( ByRef stp As gmp_int )
Declare Operator Next ( ByRef end_cond As gmp_int ) As Integer
Declare Operator Next( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer
Declare Function getString ( ByVal _base As Integer = 10 ) As String
num As mpz_ptr = 0
End Type
Declare Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As gmp_int ) As gmp_int
Declare Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Declare Operator Shl ( ByRef lhs As gmp_int, ByVal rhs As Integer ) As gmp_int
Declare Operator Shr ( ByRef lhs As gmp_int, ByVal rhs As Integer ) As gmp_int
Declare Operator - ( ByRef rhs As gmp_int ) As gmp_int
Declare Operator Not ( ByRef rhs As gmp_int ) As gmp_int
Declare Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Declare Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
#EndIf '__GMP_INT_BI__
''''#include "gmp_int.bi" 'code above
'::::::::
Constructor gmp_int ( )
num = Callocate( SizeOf( __mpz_struct ) )
mpz_init( num )
End Constructor
'::::::::
Constructor gmp_int ( ByVal i As Integer )
num = Callocate( SizeOf( __mpz_struct ) )
mpz_init_set_si( num, i )
End Constructor
'::::::::
Constructor gmp_int ( ByRef s As String, ByVal _base As Integer = 10 )
num = Callocate( SizeOf( __mpz_struct ) )
mpz_init_set_str( num, StrPtr( s ), _base )
End Constructor
'::::::::
Constructor gmp_int ( ByRef g As gmp_int )
num = Callocate( SizeOf( __mpz_struct ) )
mpz_init_set( num, g.num )
End Constructor
'::::::::
Destructor gmp_int ( )
mpz_clear( num )
DeAllocate( num )
End Destructor
'::::::::
Operator gmp_int.let ( ByRef g As gmp_int )
mpz_set( num, g.num )
End Operator
'::::::::
Operator gmp_int.let ( ByVal i As Integer )
mpz_set_si( num, i )
End Operator
'::::::::
Operator gmp_int.let ( ByRef s As String )
mpz_set_str( num, StrPtr(s), 10 )
End Operator
Operator gmp_int.cast ( ) As Integer
Operator = mpz_get_si(num)
End Operator
'::::::::
Operator gmp_int.cast ( ) As String
Operator = getString( 10 )
End Operator
'=====================================================================
' Implicit step gmp_int.For gmp_int.Next gmp_int.Step is +1
Operator gmp_int.for ( )
End Operator
Operator gmp_int.step ( )
This += 1 'this = this+1 '
End Operator
Operator gmp_int.next ( ByRef end_cond As gmp_int ) As Integer
Return This <= end_cond
End Operator
'' explicit step versions
''
Operator gmp_int.for ( ByRef step_var As gmp_int )
End Operator
Operator gmp_int.step ( ByRef step_var As gmp_int )
This += step_var 'this = this + step_var '
End Operator
Operator gmp_int.next ( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer
If step_var < 0 Then
Return This >= end_cond
Else
Return This <= end_cond
End If
End Operator
'::::::::
Function gmp_int.getString ( ByVal _base As Integer = 10 ) As String
Dim As ZString Ptr s = mpz_get_str( 0, _base, num )
If s Then
Function = *s
DeAllocate( s )
End If
End Function
'::::::::
Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_add( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_sub( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_mul( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_tdiv_q( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
' This really is quite nasty, but it's the best way I could come up with
' to do an FP divide, while rounding results the way people may expect them.
' 0.5 becomes 1, 0.4 becomes 0, -0.5 becomes -1, -0.4 becomes 0
' I'm not 100% that temp is needed, but I used it just to be safe, for some
' GMP functions it seems a bad idea to pass an mpz as dest and one of the sources.
Dim As mpf_ptr l, r, q, half, temp
Dim As gmp_int result
' size for gmp floats is fixed, this could lead to loss of precision
' the size is set by mpf_set_default_prec or by using mpf_init2( 'var', size)
' find the size of lhs and rhs, take the longest size and add 32 bit (9 digits)
Dim As UInteger l1 = mpz_sizeinbase ( lhs.num, 2 )
Dim As UInteger r1 = mpz_sizeinbase ( rhs.num, 2 )
If r1 > l1 Then l1 = r1
l1 = l1 +32
l = Callocate( SizeOf( __mpf_struct ) )
r = Callocate( SizeOf( __mpf_struct ) )
q = Callocate( SizeOf( __mpf_struct ) )
half = Callocate( SizeOf( __mpf_struct ) )
temp = Callocate( SizeOf( __mpf_struct ) )
mpf_init2( l, l1 ) ' set the size for l to l1
mpf_init2( r, l1 ) ' set the size for r to l1
mpf_init2( q, l1 ) ' set the size for q to l1
mpf_init_set_d( half, .5 )
mpf_init2( temp, l1 ) ' set the size for temp to l1
mpf_set_z( l, lhs.num )
mpf_set_z( r, rhs.num )
mpf_div( q, l, r )
Dim As Integer cmp_val = mpf_cmp_d( q, 0 )
If cmp_val > 0 Then
mpf_add( temp, q, half )
ElseIf cmp_val < 0 Then
mpf_sub( temp, q, half )
Else
mpf_set( temp, q )
End If
mpz_set_f( result.num, temp)
mpf_clear( l )
mpf_clear( r )
mpf_clear( q )
mpf_clear( half )
mpf_clear( temp )
DeAllocate( l )
DeAllocate( r )
DeAllocate( q )
DeAllocate( half )
DeAllocate( temp )
Operator = result
End Operator
'::::::::
Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_pow_ui( result.num, lhs.num, mpz_get_ui( rhs.num ) )
Operator = result
End Operator
'::::::::
Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_mod( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_and( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_ior( result.num, lhs.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_xor( result.num, lhs.num, rhs.num )
Operator = result
End Operator
Operator Shl ( ByRef lhs As gmp_int, ByVal rhs As Integer ) As gmp_int
Dim As gmp_int result
mpz_mul_2exp( result.num, lhs.num, rhs )
Operator = result
End Operator
Operator Shr ( ByRef lhs As gmp_int, ByVal rhs As Integer ) As gmp_int
Dim As gmp_int result
mpz_tdiv_q_2exp( result.num, lhs.num, rhs )
Operator = result
End Operator
'::::::::
Operator - ( ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_neg( result.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator Not ( ByRef rhs As gmp_int ) As gmp_int
Dim As gmp_int result
mpz_com( result.num, rhs.num )
Operator = result
End Operator
'::::::::
Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) = 0)
End Operator
'::::::::
Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) < 0)
End Operator
'::::::::
Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) > 0)
End Operator
'::::::::
Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) <= 0)
End Operator
'::::::::
Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) >= 0)
End Operator
'::::::::
Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Integer
Operator = (mpz_cmp( lhs.num, rhs.num ) <> 0)
End Operator
' return a string of a gmp_int number in base 2 to 62 (default 10, decimal)
Function gmp_int_2_base (ByRef bigint As gmp_int, ByVal _base As Integer = 10 ) As String
Dim As ZString Ptr s = mpz_get_str( 0, _base, bigint.num )
If s Then
Function = *s
DeAllocate( s )
End If
End Function
Code: Select all
#Include Once "gmp_int.bi"
Dim as gmp_int i, two = 2 'if the number is small
' if the number is larger than FB integer then use: two = gmp_int("2")
dim as integer k
' Powers of two
print "Some powers of two"
for i = 0 to 128
print "2 ^ " & i & " = " & two ^ i
next i
print
print "casting a gmp_int to a FreeBASIC Integer"
print "this should only be done if you know the gmp_int will fit in a Integer"
k = two
print "k = two ->";k
print
i = "1" + string(35, "0")
i = i + 1
Print i; " / 3 = "; i / 3
Print
i = gmp_int(string(40,"1"), 2)
Print "&B" + String(40,"1") + " = ";i
Print
Print i; " shr 39 = "; i Shr 39
Print
i = 1
Print i; " shl 128 = "; i Shl 128
Print
i = "1234567890"
Print i; " in base 62 = "; gmp_int_2_base(i, 62)
Print i; " in base 16 = "; gmp_int_2_base(i, 16)
Print i; " in base 8 = "; gmp_int_2_base(i, 8)
Print i; " in base 2 = "; gmp_int_2_base(i, 2)
Print
i = gmp_int("09azAZ", 62)
Print "09azAZ(62) = "; i
Sleep
-
- Posts: 231
- Joined: Apr 10, 2010 11:41
- Location: Japan
- Contact:
Re: Always for me a Big question
Dear srvaldez
Dear frisian
Thanks for your quick reply.
You two have always touched my interest and gave me perfect teachings.
I am very grateful.
Result: 1111111111111111111111111111111111111111111111111111111
Dear frisian
Thanks for your quick reply.
You two have always touched my interest and gave me perfect teachings.
I am very grateful.
Code: Select all
#Include Once "gmp_int.bi"
Dim As gmp_int a = gmp_int("123456789123456789123456789123456789123456789123456789")
Dim As gmp_int b = gmp_int("987654321987654321987654321987654321987654321987654321") ,c
c = a + b + 1
Print c
Sleep
Re: Always for me a Big question
thank you frisian for the update, perhaps you should post it in the tips & tricks section?
-
- Posts: 49
- Joined: Dec 16, 2011 3:48
Re: Always for me a Big question
Thanks as many as BIG NUMBERS for all the answers.But why gmp_int.bi does not work with fb version 0.24.0 but it is ok with version 1.05.0.thank you all again.
Re: Always for me a Big question
If you have put libgmp.a into lib/win32 in version 0.24.0 then you should remove or rename libgmp.dll.a from the same folder.
-
- Posts: 49
- Joined: Dec 16, 2011 3:48
Re: Always for me a Big question
Dear dodicat I did it but It again does not work.here is the errors
F:\Program Files\fbedit1076c\FreeBASIC-0.24.0-win32\inc\gmp.bi(136) error 9: Expected expression, found 'function' in 'declare sub __gmp_get_memory_functions(byval as typeof(function(byval as uinteger) as any ptr) ptr, byval as typeof(function(byval as any ptr, byval as uinteger, byval as uinteger) as any ptr) ptr, byval as typeof(sub(byval as any ptr, byval as uinteger)) ptr)'
F:\Program Files\fbedit1076c\FreeBASIC-0.24.0-win32\inc\gmp.bi(137) error 9: Expected expression, found 'function' in 'declare sub mp_get_memory_functions alias "__gmp_get_memory_functions"(byval as typeof(function(byval as uinteger) as any ptr) ptr, byval as typeof(function(byval as any ptr, byval as uinteger, byval as uinteger) as any ptr) ptr, byval as typeof(sub(byval as any ptr, byval as uinteger)) ptr)'
F:\Program Files\fbedit1076c\FreeBASIC-0.24.0-win32\inc\gmp.bi(136) error 9: Expected expression, found 'function' in 'declare sub __gmp_get_memory_functions(byval as typeof(function(byval as uinteger) as any ptr) ptr, byval as typeof(function(byval as any ptr, byval as uinteger, byval as uinteger) as any ptr) ptr, byval as typeof(sub(byval as any ptr, byval as uinteger)) ptr)'
F:\Program Files\fbedit1076c\FreeBASIC-0.24.0-win32\inc\gmp.bi(137) error 9: Expected expression, found 'function' in 'declare sub mp_get_memory_functions alias "__gmp_get_memory_functions"(byval as typeof(function(byval as uinteger) as any ptr) ptr, byval as typeof(function(byval as any ptr, byval as uinteger, byval as uinteger) as any ptr) ptr, byval as typeof(sub(byval as any ptr, byval as uinteger)) ptr)'