Squares

General FreeBASIC programming questions.
Locked
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Re: Squares

Post by Richard »

@Albert.
First demonstrate that your algorithm works for 10, 100 and 1000 decimal digit numbers when represented in ASCII base two. I can then accurately predict what your million decimal digit time will be.
If you can do a 10 x 10 decimal digit multiply in 100 microsec, then 100 x 100 will only take 10 milliseconds, 1k x 1k digits will take 1 second. 10k x 10k will take 100 sec, 100k x 100k will take 10ksec = 166.7 minutes = 2.78 hours. 1M x 1M will take about 11.5 days.

Remember that Log₂(10) = 3.322 so a 1 Mbyte decimal ASCII string will become a 3.322 Mbyte binary ASCII string. If you try to multiply a pair of million digit decimal numbers, represented in ASCII binary, then I doubt you will complete the calculation in less than a week. Now, stop complaining about the speed of my conversion code, prove my prediction of 1 week wrong by getting times for 10, 100 and 1000 digits.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Squares

Post by jj2007 »

albert wrote:I measured the speed of both the "number creator" and the "conversion"..
Can you show me where you did that? This part clearly measures the speed of string concatenation:

Code: Select all

   Dim as string res=""
   time1 = timer
        For a as longint = 1 To 10000
            res+=str(int(rnd*10))
        Next
    time2 = timer
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@jj2007

Heres the code i posted to you a page back..

Theres two sets of timers, 1 for building the number and 1 for the conversion.

Code: Select all

#include "Windows.bi"

 Function base2(DecimalNumber As String) As String
            Dim As String starter=DecimalNumber,ans,m,b=string(4*len(DecimalNumber),32)
             static as byte a(48 to 57)={0,10,0,10,0,10,0,10,0,10}
            Dim As long c,lens
            #macro reverse(s)
                lens=Len(s)
                For n As Integer=0 To Int((lens-1)/2):Swap s[n],s[lens-1-n]:Next
                #endmacro
                #macro div2(s,m,c)
                c=0:ans=s
                For z As long=0 To Len(s)-1
                     ans[z]=  (c+s[z]) shr 1 +24
                      c=a(s[z])
                Next z
                m= Ltrim(ans,"0")
                #endmacro
                dim as long idx
                Do
                    div2(starter,m,c)
                    b[idx]=c\10+48
                    starter=m
                    idx+=1
                Loop Until m="1" orelse m=""
                b=rtrim(b)
                reverse(b)
                b=Str(m)+b
                Return b
         End Function

screen 19

   Dim as double time1,time2
   Dim as string res=""
   
   time1 = timer
        For a as longint = 1 To 10000
            res+=str(int(rnd*10))
        Next
    time2 = timer
   
    print time2-time1 , "time to build number."
   
    time1= timer
       dim as string ans = base2(res)
    time2 = timer
   
   print time2 - time1 , "time to conveert to base2"
   
   sleep()
   
   end
   

albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@Richard

I converted your base10_to_2() to use pointers , it only speeds it up by a second or so on 1 million.
I've got to convert the acc( i ) to use a pointer into the acc( ) array..
I think array access takes 16 clocks per access.. i think an array( pointer ) takes 1 clock (not sure) ??

Code: Select all

'=======================================================================
' Convert base two ASCII binary string to base ten ASCII decimal string
'=======================================================================
Function base_2_to_10( Byref b As String ) As String    ' b may be lengthened
    ' lengthen input string by up to 28 zero bits to make 29 bit blocks
    Dim As Integer n = Len( b ) Mod 29
    If n Then b = String( 29 - n, "0" ) + b
    n = Len( b ) \ 29  ' number of input blocks
    Dim As Ulong acc( 0 To n )  ' accumulator array
    ' convert blocks of 9 digits to binary in 32 bit Ulong
    Dim As Ulongint product, carry  ' 64 bit Unsigned Integer
    Dim As Integer i, j, k = 1      ' loop counters
    For j = 1 To Len( b ) Step 29   ' the blocks to convert
        carry = Valulng( "&b" + Mid( b, j, 29 ) ) ' value of 29 bit block
        For i = 0 To k  ' Multiply Accumulate,   2^29 = 536870912
            product = ( Culngint( acc( i ) ) * 536870912ull ) + carry
            acc( i ) = product Mod 1000000000ull    ' sum is low part
            carry = product \ 1000000000ull     ' carry is the high part
        Next i
        If carry Then   ' extend accumulator by one element when needed
            k += 1
            acc( k ) = carry
        End If
    Next j  ' accumulator now contains result blocks of base 1 billion
    ' unpack and return acc as decimal ASCII string
    Dim As String txt
    For i = n To 0 Step -1
        txt += Right( "000000000" + Str( acc( i ) ), 9 )
    Next i
    Return Ltrim( txt, "0" )
End Function

'=======================================================================
' Convert base ten ASCII decimal string to base two ASCII binary string
'=======================================================================
Function base_10_to_2( Byref d As String ) As String  ' d may be lengthened
    ' lengthen input string by up to 8 digits to make 9 digit blocks
    Dim As Integer n = Len( d ) Mod 9
    If n Then d = String( 9 - n, "0" ) + d
    n = Len( d ) \ 9  ' number of input blocks
    Dim As Ulong acc( 0 To n )  ' the accumulator array
    ' convert blocks of 9 digits to binary in 32 bit Ulong
    Dim As Ulongint product, carry  ' 64 bit Unsigned Integer
    Dim As Integer i, j, k = 1      ' loop counters
    
    '================================================
    'begin alberts additons
    '================================================
    dim as string number = d
    dim as string str1
    dim as longint dec1
    do
        str1 = str(len(number)/9)
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number = "0" + number
    loop until dec1 = 0
    'convert the numeric strings to use pointers
    'convert number1
    dim as string n1 = string(len(number)*8,chr(0))
    dim as ulongint ptr ulp1
    ulp1 = cptr(ulongint ptr,strptr(n1))
    dim as longint val1
    dim as longint len_1 = 0
    dim as uinteger a
    for a = 0 to len(number)-1 step 9
        val1  = (number[a+0]-48)*100000000ull
        val1+= (number[a+1]-48)*10000000ull
        val1+= (number[a+2]-48)*1000000ull
        val1+= (number[a+3]-48)*100000ull
        val1+= (number[a+4]-48)*10000ull
        val1+= (number[a+5]-48)*1000ull
        val1+= (number[a+6]-48)*100ull
        val1+= (number[a+7]-48)*10ull
        val1+= (number[a+8]-48)*1
        *ulp1 = val1
        ulp1+=1
        len_1+=8
    next
    number = left(n1,len_1)
    n1=""
    '================================================
    'end alberts additons
    '================================================
    ulp1 = cptr(ulongint ptr,strptr(number))
    For j = 1 To Len(number)  Step 8     ' the blocks to convert
        'carry = Valulng( Mid( d, j, 9 ) ) ' get value of 9 digit block
        carry = *ulp1
        ulp1+=1
        For i = 0 To k  ' Multiply Accumulate
            product = ( culngint( acc( i ) ) * 1000000000ull ) + carry
            acc( i ) = product And &hFFFFFFFFull ' sum is low order 32 bits
            carry = product shr 32 ' carry is the high order 32 bits
        Next i
        If carry Then   ' extend accumulator by one element when needed
            k+=1
            acc( k ) = carry
        End If
    Next j  ' accumulator now contains result in packed binary
    ' unpack and return it as binary ASCII string
    Dim As String txt
    For i = n To 0 Step -1
        txt += Bin( acc( i ), 32 )
    Next i
    Return Ltrim( txt, "0" )
End Function

'=======================================================================

screen 19

dim as double time1 , time2

do
     dim as string num=""
     for a as longint = 1 to 100000 step 1
         num+=str( int(rnd*10) )
    next
    if left(num,1) = "0" then mid(num,1,1) = str(int(rnd*9)+1)
    
    time1 = timer
        dim as string binari = base_10_to_2( num )
        binari = ltrim(binari,"0")
    time2 = timer
    
    'dim as string base10 = binari
    'dim as string decimal = base_2_to_10( binari )
    
    print ltrim( num, "0")
    'print decimal
    print bin(val(num))
    print binari
    print
    print "len = " ; len(binari)
    print
    print "Time = " ; time2 - time1
    
    if inkey = " " then sleep
    
loop until inkey = chr(27)

sleep
end

Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Re: Squares

Post by Richard »

Albert wrote:I converted your base10_to_2() to use pointers , it only speeds it up by a second or so on 1 million.
I've got to convert the acc( i ) to use a pointer into the acc( ) array..
I think array access takes 16 clocks per access.. i think an array( pointer ) takes 1 clock (not sure) ??
I am convinced you are wasting your time. My code works reliably as it is, and it is easy to understand and maintain. The access time into an array depends on the level of index bound checking you do. During development you should use the maximum possible -exx checking. If that takes 16 cycles, then it is worth every nanosecond required.

Your binary ASCII multiply code does not work at all because you have not written it, and you probably never will.
If you did manage to get your code to work, it would take over a week to multiply a pair million digit numbers.

Meanwhile the Acc() inside my converters are packed binary, which is ideal for doing fast multiplies. A million by million digit multiply takes less than 10 minutes when packed, compared with your ASCII binary predicted to be one week. By avoiding binary ASCII, I can out-perform your code by a factor of more than one thousand.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Squares

Post by jj2007 »

albert wrote:Theres two sets of timers, 1 for building the number and 1 for the conversion.
OK, I see, thanks. Do you explain somewhere the logic and math of this exercise (we are at page 399 of this thread...)?

For example,

Code: Select all

        For a as longint = 1 To 9
            res+=str(int(rnd*10))
        Next
produces the number 335766299, which gets translated to 10100000000110110001100011011. So far, so good. Is it correct that you apply some BigNum logic to extend this to numbers of any bitness? If yes, for what purpose?
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@Richard

I converted your code to use pointers...
It's sped up using Geany IDE with build command ( -gen GCC -w all -O 3 "%f" )

Takes 15.?? seconds to convert 1,000,000 digits decimal to binary.
I got to find some more shortcuts.

Code: Select all

'=======================================================================
' Convert base two ASCII binary string to base ten ASCII decimal string
'=======================================================================
Function base_2_to_10( Byref b As String ) As String    ' b may be lengthened
    ' lengthen input string by up to 28 zero bits to make 29 bit blocks
    Dim As Integer n = Len( b ) Mod 29
    If n Then b = String( 29 - n, "0" ) + b
    n = Len( b ) \ 29  ' number of input blocks
    Dim As Ulong acc( 0 To n )  ' accumulator array
    ' convert blocks of 9 digits to binary in 32 bit Ulong
    Dim As Ulongint product, carry  ' 64 bit Unsigned Integer
    Dim As Integer i, j, k = 1      ' loop counters
    For j = 1 To Len( b ) Step 29   ' the blocks to convert
        carry = Valulng( "&b" + Mid( b, j, 29 ) ) ' value of 29 bit block
        For i = 0 To k  ' Multiply Accumulate,   2^29 = 536870912
            product = ( Culngint( acc( i ) ) * 536870912ull ) + carry
            acc( i ) = product Mod 1000000000ull    ' sum is low part
            carry = product \ 1000000000ull     ' carry is the high part
        Next i
        If carry Then   ' extend accumulator by one element when needed
            k += 1
            acc( k ) = carry
        End If
    Next j  ' accumulator now contains result blocks of base 1 billion
    ' unpack and return acc as decimal ASCII string
    Dim As String txt
    For i = n To 0 Step -1
        txt += Right( "000000000" + Str( acc( i ) ), 9 )
    Next i
    Return Ltrim( txt, "0" )
End Function

'=======================================================================
' Convert base ten ASCII decimal string to base two ASCII binary string
'=======================================================================
Function base_10_to_2( Byref d As String ) As String  ' d may be lengthened
    '================================================
    'begin alberts additons
    '================================================
    dim as string number = d
    dim as string str1
    dim as longint dec1
    do
        str1 = str( len(number) / 9 )
        dec1 = instr(1,str1,".")
        if dec1 <> 0 then number = "0" + number
    loop until dec1 = 0
    'convert the numeric strings to use pointers
    'convert number1
    dim as string n1 = string(len(number)*8,chr(0))
    dim as ulongint ptr ulp1
    ulp1 = cptr(ulongint ptr,strptr(n1))
    dim as longint val1
    dim as longint len_1 = 0
    dim as uinteger a
    for a = 0 to len(number)-1 step 9
        val1  = (number[a+0]-48)*100000000ull
        val1+= (number[a+1]-48)*10000000ull
        val1+= (number[a+2]-48)*1000000ull
        val1+= (number[a+3]-48)*100000ull
        val1+= (number[a+4]-48)*10000ull
        val1+= (number[a+5]-48)*1000ull
        val1+= (number[a+6]-48)*100ull
        val1+= (number[a+7]-48)*10ull
        val1+= (number[a+8]-48)*1
        *ulp1 = val1
        ulp1+=1
        len_1+=8
    next
    number = left(n1,len_1)
    n1=""
    '================================================
    'end alberts additons
    '================================================
    Dim As ulongint acc( 0 To len(number) \ 8 )  ' the accumulator array
    Dim As Ulongint product, carry  ' 64 bit Unsigned Integer
    Dim As Integer k = 1      ' loop counters
    dim as ulongint ptr ulp2
    ulp1 = cptr(ulongint ptr,strptr(number))
    For j as longint = 1 To Len(number)  Step 8     ' the blocks to convert
        'carry = Valulng( Mid( d, j, 9 ) ) ' get value of 9 digit block
        carry = *ulp1
        ulp1+=1
        ulp2 = cptr( ulongint ptr , varptr( acc(0) ) )
        For i as longint = 0 To k ' Multiply Accumulate
            product = culngint( *ulp2  * 1000000000ull ) + carry
            *ulp2 = product and 4294967295 ' sum is low order 32 bits
            carry = product shr 32 ' carry is the high order 32 bits
            ulp2+=1
        Next i
        If carry Then   ' extend accumulator by one element when needed
            k+=1
            *ulp2 = carry
        End If
    Next j  ' accumulator now contains result in packed binary
    ' unpack and return it as binary ASCII string
    Dim As String txt
    For i as longint = k to lbound(acc) Step -1
        txt+= Bin( acc(i) ,32 )
    Next i
    Return ltrim( txt , "0")
End Function

'=======================================================================
'Dodicats base2()
'=======================================================================
Function base2(DecimalNumber As String) As String
    Dim As String starter = DecimalNumber , ans , m , b = ""
    static as byte a(48 to 57) = {0,10,0,10,0,10,0,10,0,10}
    Dim As long c
        #macro div2(s,m,c)
        c = 0
        ans = s
        For z As long = 0 To Len(s)-1 step 1
            ans[z] = ( (c + s[z] ) shr 1 + 24 )
            c = a( s[z] )
        Next z
        m = Ltrim(ans,"0")
        #endmacro
        Do
            div2(starter,m,c)
            b = str( c \ 10 ) + b
            starter = m
        Loop Until m = ""
        b = rtrim(b)
        Return b
End Function     



screen 19

dim as double time1 , time2

do
     dim as string num=""
     for a as longint = 1 to 1000000  step 1
         num+=str( int(rnd*10) )
    next
    if left(num,1) = "0" then mid(num,1,1) = str(int(rnd*9)+1)
    
    dim as string bins ' = base2(num)
    
    time1 = timer
        dim as string binari = base_10_to_2( num )
    time2 = timer
    
    'dim as string base10 = binari
    'dim as string decimal = base_2_to_10( binari )
    
    print ltrim( num, "0")
    'print decimal
    print bins , len(bins)
    print
    print binari , len(binari)
    print
    print "Time = " ; time2 - time1
    
    if inkey = " " then sleep
    
loop until inkey = chr(27)

sleep
end

Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Re: Squares

Post by Richard »

@Albert. Why do you need to find more shortcuts ?
What is 15 seconds when your multiply will take a week.
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@Richard

1,000,000 digits decimal converts to 3,300,000 binary
3,300,000 / 32 = 100,000 multiplies.

1,000,000 / 7 = 100,000 multiplies..

So it should be the same or faster ( i hope. ) than my fastest multiply..
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Re: Squares

Post by Richard »

I don't think you know what you are doing. Why would you need ASCII binary, if not to delay the process? When you multiply 3.3 Mbits by 3.3 Mbits in ASCII it requires 10,890,000,000,000 partial product bits go into a massive Wallace Tree. https://en.wikipedia.org/wiki/Wallace_tree

Log₁₀( 2 ³² ) = 9.633 decimal digits per 32 bit block. 1 Mdigits / 9.633 = 103,810 blocks of 32 bits.
A 1 Mdigit × 1 Mdigit will therefore generate 103,810 ² = 10,776,568,620 partial products, each of 64 bits.
They will all have to be accumulated and carry propagated. That is how my BigInt overlay code did it.
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@Richard
@Dodicat

Here's my latest attempt at a speedy multiplier...

Code: Select all


screen 19

do
    
    dim as ulongint n1 = int(rnd*99)+1
    dim as ulongint n2 = int(rnd*99)+1
    
    if n2 > n1 then swap n1,n2
    
    
    dim as ulongint ans2 = (n1+1) * (n2-1) + ( ((n1+1)-(n2-1)) -1 )
    
    dim as ulongint ans3 = (n1+2) * (n2-2) + ( ((n1+2)-(n2-2)) *2 - 4 )
    
    dim as ulongint ans4 = (n1+3) * (n2-3) + ( ((n1+3)-(n2-3)) *3 - 9 )
    
    dim as ulongint ans5 = (n1+4) * (n2-4) + ( ((n1+4)-(n2-4)) *4 - 16 )
    
    dim as ulongint ans6 = (n1+9) * (n2-9) + ( ((n1+9)-(n2-9)) *9 - 81 )
    
    print
    print "n1  = " ; n1
    print "n2  = " ; n2
    print
    print "ans  = " ; n1*n2
    print "ans2 = " ; ans2
    print "ans3 = " ; ans3
    print "ans4 = " ; ans4
    print "ans5 = " ; ans5
    print
    print "ans6 = " ; ans6
    
    
    sleep
    
    if inkey = chr(27) then exit do
    
loop

sleep
end

My favorite time of day 7:34 ( heaven dirty whore )
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Squares

Post by dodicat »

Hi Albert.
You express the same thing each way.
VIZ:

Code: Select all


screen 12,32

dim as long y=140
#define ln(a,c) line(a,y)-(a-20,y+30),c

print "(n1+k) * (n2-k) + ((n1+k)-(n2-k))*k  -k*k"

locate 5
print " =  n1*n2 -n1*k +n2*k -k*k  +(n1+k-n2+k)*k  -k*k"

locate 10           
print " =  n1*n2 -n1*k +n2*k -k*k  +n1*k + k*k -n2*k  +k*k -k*k"
ln(105,4):ln(250,4)
ln(159,2):ln(350,2)
ln(200,7):ln(310,7)
ln(400,5):ln(440,5)

locate 15
print " = n1*n2"
sleep  
Here is similar to your ulong, destined to be a pointer.
(For jump nine people)
Please wait for the 50 cycles.

Code: Select all

screen 19
function ValulngMid(num as string, start as long=1, length as long = 0) as ulong
    if start<=0 then start=1
    dim as long L=len(num)
  if  start+length > L-1 then length = (L-start)+1
  dim as ulong  d = 1, ans
  for i as long = length-1+start-1 to start-1 step -1
    ans += (num[i]-48)*d
    d =d Shl 3+d Shl 1  ' *= 10
  next
  return ans
end function

 dim as string s=""
     for a as longint = 1 to 1000000  step 1
         s+=str( int(rnd*10) )
    next
if left(s,1) = "0" then mid(s,1,1) = str(int(rnd*9)+1)


dim as long start=100000
const length=9
dim as double t,t2,tot1,tot2

for z as long=1 to 50
t=timer
dim as ulongint u
for n as long=1 to 1000000
u= valulngmid(s,start,length)
next
t2=timer
tot1+=t2-t
print t2-t,u,"function"
sleep 50
t=timer

for n as long=1 to 1000000
u=  valulng(mid(s,start,length))
next
t2=timer
tot2+=t2-t
print t2-t,u,"valulnint"
windowtitle  str(z) + " of " + "50"
print
next z

print
print tot1,"total time for function"
print tot2,"total time for valulng"
sleep  
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

@Dodicat

I was trying to take baby steps to derive a formula.

like 1234 * 5678 , (1234 + 678) * 5000 and then figure the missing value needed to make the multiply the right answer.

Code: Select all


screen 19

do
    
    dim as string num1
    for a as longint = 1 to 2 
        num1+= str(int(rnd*10))
    next
    if left(num1,1) = "0" then mid(num1,1,1) = str(int(rnd*9)+1)
    
    dim as string num2
    for a as longint = 1 to 2 
        num2+= str(int(rnd*10))
    next
    if left(num2,1) = "0" then mid(num2,1,1) = str(int(rnd*9)+1)
    
    if num2 > num1 then swap num1,num2
    
    dim as ulongint number1 =  val(num1) + val( mid(num2,2) ) 
    dim as ulongint number2 =  val( left(num2,1) + string(len(num2)-1,"0") ) 
    
    dim as ulongint ans7 = ( number1 * number2 ) 
        
    print
    print "n1  = " ; num1
    print "n2  = " ; num2
    print
    print number1 , number2
    
    print "ans  = " ; val(num1) * val(num2)
    print "ans7 = " ; ans7 , (val(num1)*val(num2)) - ans7
    
    
    sleep
    
    if inkey = chr(27) then exit do
    
loop

sleep
end

badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Squares

Post by badidea »

Sorry to interrupt to heavy calculations, but I have some squares to post in Squares :-)

Code: Select all

#include once "fbgfx.bi"

type xy_long
	dim as long x, y
end type 

operator +(p1 as xy_long, p2 as xy_long) as xy_long
	return type(p1.x + p2.x, p1.y + p2.y)
end operator

union rgba_union
	value as ulong
	type
		b as ubyte
		g as ubyte
		r as ubyte
		a as ubyte
	end type
end union

'-------------------------------------------------------------------------------

type graphics_type ' pretty dumb graphics class
	private:
		dim as fb.Image ptr pFbImg
	public:
		dim as long w, h 'size
		declare constructor(w as long, h as long)
		declare sub activate()
		declare sub clearScreen()
		declare sub dimScreen(dimFactor as single) '0...1 
end type

constructor graphics_type(w as long, h as long)
	this.w = w : this.h = h
end constructor

sub graphics_type.activate()
	screenres w, h, 32
	pFbImg = ImageCreate(w, h)
end sub

sub graphics_type.clearScreen()
	line(0, 0)-(w - 1, h - 1), &h00000000, bf
end sub

'todo: work directly with screenbuffer
sub graphics_type.dimScreen(dimFactor as single)
	dim as integer pitch, xi, yi
	dim as any ptr pPixels
	dim as rgba_union ptr pRow
	get (0, 0)-(w - 1, h - 1), pFbImg
	if imageinfo(pFbImg, , , , pitch, pPixels) <> 0 then exit sub
	if pPixels = 0 then exit sub
	for yi = 0 to h-1
		pRow = pPixels + yi * pitch
		for xi = 0 to w-1
			pRow[xi].r *= dimFactor
			pRow[xi].g *= dimFactor
			pRow[xi].b *= dimFactor
		next
	next
	put (0, 0), pFbImg, pset
end sub

'-------------------------------------------------------------------------------

type box_type 'Axis Aligned (minimum) Bounding Box
	public:
		dim as long x, y, w, h 'center position and size
		dim as ulong c 'color
		declare constructor()
		declare constructor(x as long, y as long, w as long, h as long, c as ulong)
		declare sub draw(solid as boolean)
		declare function left() as long
		declare function right() as long
		declare function up() as long
		declare function down() as long
end type

constructor box_type()
end constructor

constructor box_type(x as long, y as long, w as long, h as long, c as ulong)
	this.x = x : this.y = y
	this.w = w : this.h = h
	this.c = c
end constructor

sub box_type.draw(solid as boolean = false)
	if solid = true then
		line(x - w \ 2, y - h \ 2)-step(w - 1, h -1), c, bf
	else
		line(x - w \ 2, y - h \ 2)-step(w - 1, h -1), c, b
	end if
end sub

function box_type.left() as long
	return x - w \ 2
end function

function box_type.right() as long
	return x + w \ 2
end function

function box_type.up() as long
	return y - h \ 2
end function

function box_type.down() as long
	return y + h \ 2
end function

'-------------------------------------------------------------------------------

var graphics = graphics_type(800, 600)
graphics.activate()

const as integer NUM_BOX = 50
dim as box_type box(NUM_BOX-1)
'box(0) = box_type(150, 100, 50, 30, &h00ff00ff)
'box(1) = box_type(650, 350, 80, 120, &h00ffff00)

dim as xy_long vBox(NUM_BOX-1)
'vBox(0) = type(+5, +3)
'vBox(1) = type(+2, +4)

dim as integer i, x, y, w, h, vx, vy
dim as ulong c

randomize timer
for i = 0 to NUM_BOX-1
	w = int(rnd * 90 + 10)
	h = int(rnd * 90 + 10)
	x = int(rnd * (graphics.w - 110) + 50)
	y = int(rnd * (graphics.h - 110) + 50)
	c = int(rnd * &h00ffffff)
	box(i) = box_type(x, y, w, h, c)
	vx = (int(rnd * 2) * 2 - 1) * (int(rnd * 1) + 1)
	vy = (int(rnd * 2) * 2 - 1) * (int(rnd * 1) + 1)
	vBox(i) = type(vx, vy)
next

while inkey <> chr(27)
	for i = 0 to NUM_BOX-1
		if (box(i).left + vBox(i).x < 0) or (box(i).right + vBox(i).x > graphics.w - 1) then
			vBox(i).x = -vBox(i).x
		end if
		box(i).x += vBox(i).x
		if (box(i).up + vBox(i).y < 0) or (box(i).down + vBox(i).y > graphics.h - 1) then
			vBox(i).y = -vBox(i).y
		end if
		box(i).y += vBox(i).y
	next
	
	screenlock
	'graphics.clearScreen
	graphics.dimScreen(0.95)
	for i = 0 to NUM_BOX-1
		box(i).draw(0)
	next
	screenunlock
	sleep 15
wend
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Squares

Post by albert »

I've got a formula figured out...I got to go over it some more , making sure i'm not stupid!!
It seems to work for all digit sizes 2 to 8

I just kept blindly typing in stuff , til i got it to work?? It works.. Now to convert it to strings..

Code: Select all


screen 19

do
    
    dim as string num1
    for a as longint = 1 to 4
        num1+= str(int(rnd*10))
    next
    if left(num1,1) = "0" then mid(num1,1,1) = str(int(rnd*9)+1)
    
    dim as string num2
    for a as longint = 1 to 4
        num2+= str(int(rnd*10))
    next
    if left(num2,1) = "0" then mid(num2,1,1) = str(int(rnd*9)+1)
    
    if num2 > num1 then swap num1,num2
    
    dim as ulongint number1 =  val(num1) + val( mid(num2,2) ) 
    dim as ulongint number2 =  val( left(num2,1) + string(len(num2)-1,"0") ) 
    
    dim as ulongint ans7 = ( number1 * number2 ) + ( val(num1) * val(right(num2,len(num2)-1)) ) - ( val(num2)  * val(right(num2,len(num2)-1)) ) + (val(right(num2,len(num2)-1))^2)
        
    print
    print "n1  = " ; num1
    print "n2  = " ; num2
    print
    print "ans   = " ; val(num1) * val(num2)
    print "my ans = " ; ans7 , (val(num1)*val(num2)) - ans7
    
    sleep
    
    if inkey = chr(27) then exit do
    
loop

sleep
end

Locked