Bueno, me hacia falta hacer una funcion de este tipo para un trabajito que estoy haciendo :silbar:... y he pensado que tal vez os seria util...
Public Function IsItPrime(ByVal lNumber As Long) As Boolean
Dim i As Long
If (lNumber > 2) And (lNumber Mod 2) Or (lNumber = 2) Then
For i = 2 To (lNumber ^ 0.5)
If (lNumber Mod i) = 0 Then
GoTo Exit_
End If
Next i
IsItPrime = True
End If
Exit_:
End Function
Podriamos hacer un jueguecito... a ver quien lo hace mas rapido/corto :D Os apuntais?
MOD: Yo utilizo este codigo para comprobar lo optimizado que esta:
Option Explicit
Private n As Long
Private Sub Form_Load()
Dim x As Long
Timer1.Interval = 10
Timer1.Enabled = True
For x = 0 To 10 ^ 6
Call IsItPrime(x)
DoEvents
Next x
Timer1.Enabled = False
MsgBox n * 10 & " ms"
End Sub
Public Function IsItPrime(ByVal lNumber As Long) As Boolean
Dim i As Long
If (lNumber > 2) And (lNumber Mod 2) Or (lNumber = 2) Then
For i = 2 To (lNumber ^ 0.5)
If (lNumber Mod i) = 0 Then
GoTo Exit_
End If
Next i
IsItPrime = True
End If
Exit_:
End Function
Private Sub Timer1_Timer()
n = n + 1
End Sub
If (lNumber > 2) And (lNumber Mod 2) Then
Al 2 lo evalúas?
Ahora en visual basic se puede modificar el long para que únicamente tome los enteros positivos?
Cita de: cbug en 7 Julio 2010, 12:45 PM
If (lNumber > 2) And (lNumber Mod 2) Then
Al 2 lo evalúas?
Ahora en visual basic se puede modificar el long para que únicamente tome los enteros positivos?
Cierto, habia olvidado que el 2 tambien es primo :laugh: ;) (
Ahora lo corrijo Correjido ;))
Se puede utilizar un Integer, aunque tambien acepta Negativos... Pero solo enteros :-\
CitarSe puede utilizar un Integer, aunque tambien acepta Negativos... Pero solo enteros
:-\ Claro, porque de acuerdo a la definición, los números primos son aquellos números naturales que...
Pero igual, tu código creo que es el más eficiente en cuanto a complejidad, no sé cómo se tratará el goto en vb realmente... sin embargo, creo que se parece mucho al de la criba de eratóstenes...
Saludos!
Me quedó una duda, en el primer for lo haces hasta la raíz cuadrada del número para que sea más eficiente cierto? (Osea, tarde menos tiempo)
Está bien aunque es sencillo, y no comprueba si el 1 es primo o no (no digas nada) :xD
Cita de: cbug en 7 Julio 2010, 12:58 PM
CitarSe puede utilizar un Integer, aunque tambien acepta Negativos... Pero solo enteros
:-\ Claro, porque de acuerdo a la definición, los números primos son aquellos números naturales que...
Pero igual, tu código creo que es el más eficiente en cuanto a complejidad, no sé cómo se tratará el goto en vb realmente... sin embargo, creo que se parece mucho al de la criba de eratóstenes...
Saludos!
He pensado en usar la criba de Eratostenes pero es mas para generar una lista de primos, solo quiero comprobar si un número lo es :D
Cita de: Dreamaker en 7 Julio 2010, 13:00 PM
Me quedó una duda, en el primer for lo haces hasta la raíz cuadrada del número para que sea más eficiente cierto? (Osea, tarde menos tiempo)
Está bien aunque es sencillo, y no comprueba si el 1 es primo o no (no digas nada) :xD
No es necesario recorrer cada numero, con llegar a la raiz es suficiente :) No dire nada sobre el 1 :rolleyes: :xD
'0 ---> Invalido
'1 ---> No Primo
'2 ---> Primo
Option Explicit
Private Function Check_Prime_Number(ByVal lNumber As Long) As Byte
Dim x As Long
If lNumber >= 2 Then
Check_Prime_Number = 2
For x = 2 To (lNumber ^ 0.5)
If (lNumber Mod x) = 0 Then
Check_Prime_Number = 1
Exit For
End If
Next
End If
End Function
@Psyke: Tu función es mucho mas lenta, ademas, no tiene en cuenta que el 2 es primo (como hacia la mia :rolleyes: :xD)
No es necesario que recorras todos los números, con llegar a la raiz es suficiente ;)
Ok, agradezco la correcion, lo no tuve en cuenta :P
Ahora lo corregi!
Salu2! ;)
Private Function CheckPrimality(ByVal lNum As Long) As Boolean
Dim i As Long
Dim lSqr As Long
If lNum Mod 2 = 0 Then GoTo Composite:
lSqr = Sqr(lNum)
i = 3
Do Until i > lSqr
If lNum Mod i = 0 Then GoTo Composite:
i = i + 2
Loop
Prime:
CheckPrimality = True
Exit Function
Composite:
If lNum = 2 Then CheckPrimality = True
End Function
Cita de: cobein en 8 Julio 2010, 09:17 AM
Private Function CheckPrimality(ByVal lNum As Long) As Boolean
Dim i As Long
Dim lSqr As Long
If lNum Mod 2 = 0 Then GoTo Composite:
lSqr = Sqr(lNum)
i = 3
Do Until i > lSqr
If lNum Mod i = 0 Then GoTo Composite:
i = i + 2
Loop
Prime:
CheckPrimality = True
Exit Function
Composite:
If lNum = 2 Then CheckPrimality = True
End Function
Exelente COBEIN, este es más rápido
Saludos
Muy bueno Cobein :) No habia pensando que podrian saltarse los pares :laugh: ;)
He optimizado el primero que puse:
Public Function IsItPrime(ByVal lNumber As Long) As Boolean
Dim i As Long
If (lNumber > 2) And (lNumber And 1) Or (lNumber = 2) Then
For i = 3 To Sqr(lNumber) Step 2
If (lNumber Mod i) = 0 Then GoTo Exit_
Next i
IsItPrime = True
End If
Exit_:
End Function
Saludos :D
Una pregunta Karcrack, porque pones que vaya a la etiqueta Exit_ y no pones Exit Function??
Salu2!
Cita de: *PsYkE1* en 8 Julio 2010, 14:48 PM
Una pregunta Karcrack, porque pones que vaya a la etiqueta Exit_ y no pones Exit Function??
Salu2!
No lo habia pensado :laugh: , pero bueno, no interfiere en la velocidad, solo se llama una vez :P
Cita de: Karcrack en 8 Julio 2010, 14:53 PM
Cita de: *PsYkE1* en 8 Julio 2010, 14:48 PM
Una pregunta Karcrack, porque pones que vaya a la etiqueta Exit_ y no pones Exit Function??
Salu2!
No lo habia pensado :laugh: , pero bueno, no interfiere en la velocidad, solo se llama una vez :P
FAIL! :xD
Che la verdad muy bueno estos pequeños "concursos" de algoritmos que estan proponiendo ultimamente. Lastima que no sea muy bueno precisamente en algoritmos XD
Mmm estaría bueno un topic lleno de ejercicios de algoritmos aportados por todos (no se si hay alguno ya), por ejemplo averiguar los primeros 100 números vampiros y cosas así, son muy buenas cosas para practicar programación, obviamente en VB :xD
PD: Deberían comprometerse todos a agregar ejercicios y sólo eso, las dudas en topics aparte
En la sección Ejercicios de programación existen muchos ejercicios, que se pueden resolver en cualquier lenguaje, ya que vb no es el único.
Cita de: cbug en 9 Julio 2010, 14:02 PM
En la sección Ejercicios de programación existen muchos ejercicios, que se pueden resolver en cualquier lenguaje, ya que vb no es el único.
:laugh: :laugh: :laugh: En serio? :o :o
Cita de: Karcrack en 9 Julio 2010, 14:17 PM
Cita de: cbug en 9 Julio 2010, 14:02 PM
En la sección Ejercicios de programación existen muchos ejercicios, que se pueden resolver en cualquier lenguaje, ya que vb no es el único.
:laugh: :laugh: :laugh: En serio? :o :o
jaaaaaaaaajajajja :laugh: :laugh:
A proposito, creo que se podria mejorar las funciones aun mas
Karcrack, me explico:
Segun lo que hizo
Cobein no comprobaba los numeros pares y eso ahorra trabajo, pero teniendo en cuenta que un numero primo solo puede acabar en:
1,3,7,9
Con la funciones que hay se comprobarian los imapares:
1,3,5,7,9
Pero todo numero que acabe en 5 es imposible que sea primo, me explico?
Corregidme si me equivoco... :P
Salu2!
*PsYkE1* suena correcto lo que decis, el problema, en mi opinion es que para no comparar algun numero terminado en 5, agregarias mas operaciones que simplemente comprobandolo.
Tienes, razon, cualquier numero mayor que 5 acabado en 5 no es primo debido a que ya seria divisible por 5 (Recordemos que los multiplos de 5 son todos los numeros acabados en 5 y en 0)
Tampoco creas que augmenta mucho la velocidad, debido a que simplemente ha de hacer un Mod 3 antes que el Mod 5 para comprobar que acaba en 5...
Ademas, no se me ocurre una forma de comprobar que acabase en 5 sin ralentizar el proceso...
CitarAdvertencia - mientras estabas escribiendo, una nueva respuesta fue publicada. Probablemente desees revisar tu mensaje.
No, gracias ;)
Ok, gracias por contestar :P
EDITO:
Hice esta funcion, no es la mas rapida, pero es una forma diferente de hacerlo:
Public Function Check_Prime_Number(ByVal lNumber As Long) As Boolean
Const sPrimeDigit As String = "1379"
Dim sLastDigit As String * 1
Dim sNumber As String
Dim x As Long
If (lNumber > 2) Then
sNumber = Str$(lNumber)
sLastDigit = Right$(sNumber, 1)
If InStr(sPrimeDigit, sLastDigit) > 0 Then
For x = 3 To Sqr(lNumber) Step 2
If (lNumber Mod x) = 0 Then Exit Function
Next
Check_Prime_Number = True
End If
End If
End Function
Funcion Karcrack : 3030 ms
Funcion *PsYkE1* : 3840 ms
Funcion Cobein : 4260 ms
Decirme vuestra opinion! ;)
Apropósito si que me quedó una duda, como se fijan el tiempo que tarda en resolverlo exactamente cada función? (Como puso recién *PsYkE1*, eso me serviría para ver cuan eficientes son mis aplicaciones
@PsYkE1: Debes comprobar la velocidad con el proyecto compilado, si no no es de fiar... por ejemplo, el codigo de Cobein era un poco mas rapido que el mio cuando lo prove...
Para hacer tu codigo mas rapido deberias hacer la comprobacion trabajando con los bits... voy a ver si puedo hacer algo sin pasarlo a String... que eso consume
muchoMOD:Tu codigo falla con el 2 y el 5, que son primos y devuelve False ;)
MOD2:Acabo de hacer los Test de Velocidad:
- Karcrack: 1320ms
- Cobein: 1330ms
- Psyke: 2360ms
He hecho la prueba con un ciclo desde el 3 a 10^6 :D
Option Explicit
Private n As Long
Private Sub Form_Load()
Dim x As Long
Timer1.Interval = 10
Timer1.Enabled = True
For x = 3 To 10 ^ 6
Call IsItPrime(x)
DoEvents
Next x
Timer1.Enabled = False
MsgBox n * 10 & " ms" & " KARCRACK"
n = 0
Timer1.Enabled = True
For x = 3 To 10 ^ 6
Call CheckPrimality(x)
DoEvents
Next x
Timer1.Enabled = False
MsgBox n * 10 & " ms" & " COBEIN"
n = 0
Timer1.Enabled = True
For x = 3 To 10 ^ 6
Call Check_Prime_Number(x)
DoEvents
Next x
Timer1.Enabled = False
MsgBox n * 10 & " ms" & " Psyke"
n = 0
End Sub
Public Function Check_Prime_Number(ByVal lNumber As Long) As Boolean
Const sPrimeDigit As String = "1379"
Dim sLastDigit As String * 1
Dim sNumber As String
Dim x As Long
If (lNumber > 2) Then
sNumber = Str$(lNumber)
sLastDigit = Right$(sNumber, 1)
If InStr(sPrimeDigit, sLastDigit) > 0 Then
For x = 3 To Sqr(lNumber) Step 2
If (lNumber Mod x) = 0 Then Exit Function
Next
Check_Prime_Number = True
End If
End If
End Function
Private Function CheckPrimality(ByVal lNum As Long) As Boolean
Dim i As Long
Dim lSqr As Long
If lNum Mod 2 = 0 Then GoTo Composite:
lSqr = Sqr(lNum)
i = 3
Do Until i > lSqr
If lNum Mod i = 0 Then GoTo Composite:
i = i + 2
Loop
Prime:
CheckPrimality = True
Exit Function
Composite:
If lNum = 2 Then CheckPrimality = True
End Function
Public Function IsItPrime(ByVal lNumber As Long) As Boolean
Dim i As Long
If (lNumber >= 2) And (lNumber And 1) Or (lNumber = 2) Then
For i = 3 To Sqr(lNumber) Step 2
If (lNumber Mod i) = 0 Then Exit Function
Next i
IsItPrime = True
End If
End Function
Private Sub Timer1_Timer()
n = n + 1
End Sub
S2 ;)
Karcrack, seria mas exacto si usaras GetTickCount ;-D
Cita de: raul338 en 9 Julio 2010, 19:39 PM
Karcrack, seria mas exacto si usaras GetTickCount ;-D
Simplemente queremos ver quien es mas rapido, tampoco necesitamos mas precision, si la necesitasemos usaria QueryPerformanceCounter (http://msdn.microsoft.com/en-us/library/ms644904%28VS.85%29.aspx) ;)
Private Function CheckPrimality(ByVal lNum As Long) As Boolean
Dim i As Long
If lNum < 10 Then
If lNum = 2 Then CheckPrimality = True: Exit Function
If lNum = 5 Then CheckPrimality = True: Exit Function
If lNum = 1 Then Exit Function
End If
If Not (lNum And 1) = 1 Then Exit Function
If (lNum And 5) = 5 Then Exit Function
For i = 3 To Sqr(lNum) Step 2
If lNum Mod i = 0 Then Exit Function
Next
CheckPrimality = True
End Function
Test project: http://uploading.com/files/c72amae6/Prime.rar/
No estoy seguro si la clase para testear la velocidad esta en la descarga, si no esta la pueden descargar de aca http://www.xbeat.net/vbspeed/download/CTiming.zip
uuuu vuela la ultima, es casi la mitad de la primera que posteaste al principio.
y si lo del timer para medir la velocidad mm no es de fiar mas que nada por el doevents mejor usar GetTickCount o QueryPerformanceCounter.
Private Function CheckPrimality(ByVal lNum As Long) As Boolean
Dim i As Long
If lNum < 10 Then
If lNum = 2 Then CheckPrimality = True: Exit Function
If lNum = 5 Then CheckPrimality = True: Exit Function
If lNum = 1 Then Exit Function
End If
If Not (lNum And 1) = 1 Then Exit Function
If (lNum And 5) = 5 Then Exit Function
For i = 3 To Sqr(lNum) Step 2
If lNum Mod i = 0 Then Exit Function
Next
CheckPrimality = True
End Function
Interesante linea... con eso se puede comprobar si es multiple de 5? No acabo de entender como funciona... voy a jugar un poco con los Bits...
Pues eso, Cobein vence :P A no ser que alguien encuentre una forma de calcular la multiplicidad mas rapida que con Mod :laugh: :laugh:
Felicidades, fue divertido :P Habran mas de estos seguro >:D :xD
Ok, lo siento por las medidas, quizas hice algo mal sin darme cuenta... :-\
Tengo curiosidad a ver como lo haces Karcrack :), me gustan este tipo de retos, aprendo mucho y salen diferentes manera de hacer las cosas... :P
Salu2! ;)
Cita de: Karcrack en 9 Julio 2010, 20:52 PM
Felicidades, fue divertido :P Habran mas de estos seguro >:D :xD
COBEIN WINS! Fatality :xD
Ps.... estare esperando haber si puedo participar :)
Advertencia - mientras estabas escribiendo, una nueva respuesta fue publicada. Probablemente desees revisar tu mensaje.
:¬¬
Hay un error en el codigo, despues lo corrijo.
Cita de: cobein en 10 Julio 2010, 05:31 AM
Hay un error en el codigo, despues lo corrijo.
Bueno, el error para quien quiera saberlo es que comprobaba mal la multiplicidad de 5...
Me he quedado hoy pensando... y hay una forma realmente sencilla de obtener el ultimo digito de una cifra... sin usar cadenas de textoooo :o Simplemente hay que obtener el resto al dividir por 10 (aka Mod 10) :laugh:
He hecho este codigo :D, si no me equivoco es la mas rapida (sin contar la de Cobein, que no acaba de funcionar)
Public Function IsItPrime(ByVal lNumber As Long) As Boolean
Dim i As Long
If lNumber < 10 Then
If lNumber = 2 Then IsItPrime = True: Exit Function
If lNumber = 5 Then IsItPrime = True: Exit Function
If lNumber = 1 Then Exit Function
ElseIf (lNumber And 1) Then
Select Case (lNumber Mod 10)
Case 1, 3, 7, 9
For i = 3 To Sqr(lNumber) Step 2
If (lNumber Mod i) = 0 Then Exit Function
Next i
IsItPrime = True
End Select
End If
End Function
WOow que bueno!! :D
A ver si cuando acabe examenes me meto a tope con bytes. :)
Tu code es muy sencillo y eficaz! :D
Una cosilla de nada:
Si quitas el indicador en el For ahorras un poquitin (muy poco) de tiempo... ;)
http://foro.rthacker.net/programacion-visual-basic/como-acelerar-codigo-en-vb6/
DoEvents¡! :P
Cita de: *PsYkE1* en 30 Agosto 2010, 22:29 PM
Una cosilla de nada:
Si quitas el indicador en el For ahorras un poquitin (muy poco) de tiempo... ;)
http://foro.rthacker.net/programacion-visual-basic/como-acelerar-codigo-en-vb6/
DoEvents¡! :P
Estas equivocado :P
http://www.xbeat.net/vbspeed/c_ForNext.htm
Despite all rumors: Next or Next i does NOT matter at all!! The minimal differences you see in the timings above are totally insignificant: you could produce any possible ranking order by running the same test over and over again long enough.
Esa pequeña diferencia de tiempo va a favor de uno u otro dependiendo de cada vez que lo ejecutas...
:o
Ok tu ganas... :silbar:
DoEvents¡! :P