Attribute VB_Name = "bas_k0_rand"
'========================================================================
' Manuel de la Herrán Gascón - mherran@aircenter.net
'========================================================================
Option Explicit
Option Base 1
'------------------------------------------------------------------------
' k: módulos comunes a más de un proyecto
' Este módulo contiene:
' Funciones pseudoaleatorias (casi azar)
' Pseudorandom functions
'------------------------------------------------------------------------
' Funciones que generan valores pseudoaleatorios
' distribuyéndose la probabilidad de los valores
' según cierta distribución estimada
' Todas las funciones se basan en la función de ruido blanco (uniforme):
' randDistContUnif01
' Si se cambia el metodo de calcular esta función,
' se cambiará el efecto de todas las demás
' Como opciones a la hora de calcular randDistContUnif01 se ofrecen:
' - Rnd de Visual Basic
' - Los N primeros decimales del número PI contenidos en un fichero
' - El contenido de un fichero cualquiera
'------------------------------------------------------------------------
' ABREVIATURAS
' Unif=Uniforme: todos los valores tienen igual probabilidad
' Norm=Normal: las probabilidades se distribuyen en forma de campana de Gauss
' Bern=Bernoulli: discreta, dos valores con probabilidad elegida por el usuario
' User=Usuario: discreta, N valores con probabilidades elegidas por el usuario
' Disc=discreta: los valores devueltos están separados por una distancia constante conocida Step (habitualmente Step=1)
' Cont=pseudoContinua: se devuelve un valor con el máximo detalle en decimales soportado por el ordenador (double)
' Lb=Lower Bound: Límite Inferior del valor devuelto, inclusive
' Ub=Upper Bound: Límite Superior del valor devuelto, inclusive
' Step=paso: distancia entre unos y otros valores en una distribución discreta (habitualmente Step=1)
' M=media, valor medio de todos los valores devueltos (positivo o negativo)
' Dt=desviación típica, dispersión. Indica la forma de la campana de Gauss. Raiz cuadrada de la varianza
' Dt siempre es positivo, entre 0 e infinito
' Dt>1 Leptocúrtica, estirada, muy concentrados, montaña
' Dt=1 Mesocúrtica, aspecto clasico de de Normal(0,1) gaussiana, colina
' Dt<1 Platocúrtica, achatada, muy dispersos, tiende a una uniforme, duna
' Nota: La media no tiene porqué estar entre Lb y Ub
' El caso normal es Lb < M < Ub, pero no es obligatorio
'------------------------------------------------------------------------
' Notas:
' Todas las distribuciones continuas devuelven un double
' Cuando hay probabilidades como parametros de entrada,
' estas probabilidades son valores double entre 0 y 1
'------------------------------------------------------------------------
' ===DISCRETAS===
' randDistDiscUnifTrueFalse_b
' randDistDiscUnif01_i
' randDistDiscUnif01_l
' randDistDiscUnifLbUbStep_d
' randDistDiscUnifLbUbStepExceptionUser_d
' randDistDiscUnif1Ub1_i
' randDistDiscUnif1Ub1_l
' randDistDiscUnifLbUb1_i
' randDistDiscUnifLbUb1_l
' randDistDiscNormLbUbMDtStep_d
' randDistDiscBernTrueFalse_b
' randDistDiscBern01_i
' randDistDiscBern01_l
' randDistDiscUser_d
' randDistDiscUser_s
' randDistDiscUser_l
' randDistDiscUser_i
' ===CONTINUAS===
' randDistContUnif01
' randDistContUnif1Ub
' randDistContUnifLbUb
' randDistContNormLbLbUbMDt
'------------------------------------------------------------------------
' AGRADECIMIENTOS: (contributed by:)
'
' Héctor Rodrigo
' ==============
' Método de cálculo de Normal(0,1) mediante el teorema central del límite
' y ampliación del método de calculo de Normal(0,1) para el cálculo de Normal(m,v)
' (Este método es el método elegido)
'
' Phil Beffrey y Mattias Fagerlund
' ================================
' phil@pixar.com, matfa@acacia.se
' Método de cálculo de Normal mediante el cálculo de la media
' de varios numeros (unos 12 ejemplos) generados al azar con una distribucion uniforme
'
' Evan Hughes y Antonio Carpintero Sanchez
' ========================================
' E.J.Hughes@rmcs.cranfield.ac.uk
' http://www.rmcs.cranfield.ac.uk/~daps/daps/pgrads/e_h/hughes.htm
' amcarpintero@polar.es
'
' Box-Muller method
' Método de cálculo de Normal mediante el algoritmo obtenido de:
' author = "William H. Press and Brian P. Flannery and Saul A. Teukolsky and William T. Vetterling"
' Title = "{NUMERICAL RECIPES} The Art Of Scientific Computing ({FORTRAN}Version)"
' publisher = "Cambridge University Press"
' Year = "1989"
' Existe tambien el libro "NUMERICAL RECIPES IN C", de William H. Press)
'------------------------------------------------------------------------


'Fichero de Azar
Global digitos_azar() As Integer 'chorro de numeros
Global azar_en_memoria As Boolean 'dice si efectivamente esta cargada o no la serie de numeros
Global indice_azar As Long 'puntero al valor actual del chorro de numeros

'Gauss
Global hay_solucion_anterior_gauss  As Boolean
Global solucion_anterior_gauss As Double
Function randDistDiscUnifTrueFalse_b() As Boolean
    If randDistContUnif01 < 0.5 Then
        randDistDiscUnifTrueFalse_b = True
    Else
        randDistDiscUnifTrueFalse_b = False
    End If
End Function
Function randDistDiscUnif01_i() As Integer
'Ojo: es int (parte entera) y no cint (convertir a integer)
    randDistDiscUnif01_i = Int(randDistContUnif01 + 0.5)
End Function
Function randDistDiscUnif01_l() As Long
'Ojo: es int (parte entera) y no cint (convertir a integer)
    randDistDiscUnif01_l = Int(randDistContUnif01 + 0.5)
End Function
Function randDistDiscUnifMemLbUbMDt_d(Lb As Double, Ub As Double, myStep As Double, M As Double, Dt As Double) As Double
'Creamos un numero con todos los decimales en continua
'Le quitamos lo que le sobra al numero para dejarlo en unidades de Step
    Dim continua As Double
    Dim cociente As Double
    continua = randDistContNormMemLbUbMDt(Lb, Ub, M, Dt)
    cociente = continua / myStep
    randDistDiscUnifMemLbUbMDt_d = continua - myStep * (cociente - Int(cociente))
End Function
Function randDistDiscUnifLbUbStep_d(Lb As Double, Ub As Double, myStep As Double) As Double
'Creamos un numero con todos los decimales en continua
'Le quitamos lo que le sobra al numero para dejarlo en unidades de Step
    Dim continua As Double
    Dim cociente As Double
    continua = ((Ub - Lb + 1) * randDistContUnif01 + Lb)
    cociente = continua / myStep
    randDistDiscUnifLbUbStep_d = continua - myStep * (cociente - Int(cociente))
End Function
Function randDistDiscUnifLbUbStepExceptionUser_d(Lb As Double, Ub As Double, myStep As Double, dataSet() As Double, probSet() As Double, totalExceptionProb As Double) As Double
'Con una probabilidad de totalExceptionProb
'se comporta como una distribución de probabilidad de usuario
'y en caso contrario es una normal
'El objetivo de esto es, por ejemplo, obtener una distribución
'normal con algunas excepciones con mucha probabilidad
    If randDistDiscBernTrueFalse_b(totalExceptionProb) Then
        'Va a salir un numero que es del conjunto de excepciones
        randDistDiscUnifLbUbStepExceptionUser_d = randDistDiscUser_d(dataSet(), probSet())
    Else
        randDistDiscUnifLbUbStepExceptionUser_d = randDistDiscUnifLbUbStep_d(Lb, Ub, myStep)
    End If
End Function
Function randDistDiscUnif1Ub1_i(Ub As Integer) As Integer
'Devuleve un número al azar entero
'entre 1 y fin, inclusive ambos
'La probabilidad es igual para todos los números
'Ojo: es int (parte entera) y no cint (convertir a integer)
    randDistDiscUnif1Ub1_i = Int(Ub * randDistContUnif01 + 1)
End Function
Function randDistDiscUnif1Ub1_l(Ub As Long) As Long
'Devuleve un número al azar entero
'entre 1 y fin, inclusive ambos
'La probabilidad es igual para todos los números
'Ojo: es int (parte entera) y no cint (convertir a integer)
    randDistDiscUnif1Ub1_l = Int(Ub * randDistContUnif01 + 1)
End Function
Function randDistDiscUnifLbUb1_i(Lb As Integer, Ub As Integer) As Integer
'Devuleve un número al azar entero
'entre inicio y fin, inclusive ambos
'La probabilidad es igual para todos los números
'Se admiten valores negativos
    'Metodo 1
    'randDistDiscUnifLbUb1_i = randDistDiscUnif1Ub1_i(Ub - Lb + 1) + Lb - 1
    'Metodo 2
    randDistDiscUnifLbUb1_i = Int((Ub - Lb + 1) * randDistContUnif01 + Lb)
End Function
Function randDistDiscUnifLbUb1_l(Lb As Long, Ub As Long) As Long
'Devuleve un número al azar entero
'entre inicio y fin, inclusive ambos
'La probabilidad es igual para todos los números
'Se admiten valores negativos
    'Metodo 1
    'randDistDiscUnifLbUb1_l = randDistDiscUnif1Ub1_l(Ub - Lb + 1) + Lb - 1
    'Metodo 2
    randDistDiscUnifLbUb1_l = Int((Ub - Lb + 1) * randDistContUnif01 + Lb)
End Function
Function randDistDiscNormLbUbMDtStep_d(Lb As Double, Ub As Double, M As Double, Dt As Double, myStep As Double) As Double
'Creamos un numero con todos los decimales en continua
'Le quitamos lo que le sobra al numero para dejarlo en unidades de Step
'Ejemplo de uso:
'randDistDiscNormLbUbMDtStep_d(1, 100, 50, 5, 1)
'Devuelve un numero entero (Step=1)
'entre 1 y 100
'el 50 es el mas probable (media)
'y los menos probables son el 1 y el 100
    Dim continua As Double
    Dim cociente As Double
    continua = randDistContNormLbUbMDt(Lb, Ub, M, Dt)
    cociente = continua / myStep
    randDistDiscNormLbUbMDtStep_d = continua - myStep * (cociente - Int(cociente))
End Function
Sub randDistDiscNorm2DLbUbMDtStep_d(Lb As Double, Ub As Double, MD1 As Double, MD2 As Double, Dt As Double, myStep As Double, retD1 As Double, retD2 As Double)
    Dim continua As Double
    Dim cociente As Double
    continua = randDistContNormLbUbMDt(Lb, Ub, MD1, Dt)
    cociente = continua / myStep
    retD1 = continua - myStep * (cociente - Int(cociente))
    continua = randDistContNormLbUbMDt(Lb, Ub, MD2, Dt)
    cociente = continua / myStep
    retD2 = continua - myStep * (cociente - Int(cociente))
End Sub
Function randDistDiscMultiNormLbUbMDtStep_d(Lb As Double, Ub As Double, M() As Double, Dt As Double, myStep As Double) As Double
'Se elige una de las medias con probabilidad uniforme
    Dim continua As Double
    Dim cociente As Double
    continua = randDistContNormLbUbMDt(Lb, Ub, M(randDistDiscUnifLbUb1_l(LBound(M), UBound(M))), Dt)
    cociente = continua / myStep
    randDistDiscMultiNormLbUbMDtStep_d = continua - myStep * (cociente - Int(cociente))
End Function
Function randDistDiscBernTrueFalse_b(pTrue As Double) As Boolean
    If randDistContUnif01 < pTrue Then
        randDistDiscBernTrueFalse_b = True
    Else
        randDistDiscBernTrueFalse_b = False
    End If
End Function
Function randDistDiscBern01_i(pZero As Double) As Integer
    If randDistContUnif01 < pZero Then
        randDistDiscBern01_i = 0
    Else
        randDistDiscBern01_i = 1
    End If
End Function
Function randDistDiscBern01_l(pZero As Double) As Long
    If randDistContUnif01 < pZero Then
        randDistDiscBern01_l = 0
    Else
        randDistDiscBern01_l = 1
    End If
End Function
Function randDistDiscUserUnif_d(dataSet() As Double) As Double
'Devuelve uno al azar de los valores de dataSet
'con una probabilidad uniforme
    Dim i As Long
    i = randDistDiscUnifLbUb1_l(LBound(dataSet), UBound(dataSet))
    randDistDiscUserUnif_d = dataSet(i)
End Function
Function randDistDiscUserUnif_i(dataSet() As Integer) As Integer
'Devuelve uno al azar de los valores de dataSet
'con una probabilidad uniforme
    Dim i As Long
    i = randDistDiscUnifLbUb1_l(LBound(dataSet), UBound(dataSet))
    randDistDiscUserUnif_i = dataSet(i)
End Function
Function randDistDiscUserUnif_l(dataSet() As Long) As Long
'Devuelve uno al azar de los valores de dataSet
'con una probabilidad uniforme
    Dim i As Long
    i = randDistDiscUnifLbUb1_l(LBound(dataSet), UBound(dataSet))
    randDistDiscUserUnif_l = dataSet(i)
End Function
Function randDistDiscUserUnif_s(dataSet() As String) As String
'Devuelve uno al azar de los valores de dataSet
'con una probabilidad uniforme
    Dim i As Long
    i = randDistDiscUnifLbUb1_l(LBound(dataSet), UBound(dataSet))
    randDistDiscUserUnif_s = dataSet(i)
End Function
Function randDistDiscUser_d(dataSet() As Double, probSet() As Double) As Double
'Devuelve uno al azar de los valores de dataSet
'con una probabilidad que es la expresada en probSet
    Dim azar As Double
    Dim i As Long
    Dim numElem As Long
    numElem = UBound(dataSet) - LBound(dataSet) + 1
    If numElem <> UBound(probSet) - LBound(probSet) + 1 Then Exit Function
    ReDim tope(1 To numElem) As Double
    If numElem = 1 Then
        randDistDiscUser_d = dataSet(1)
        Exit Function
    End If
    tope(1) = probSet(1)
    For i = 2 To numElem
        tope(i) = tope(i - 1) + probSet(i)
    Next i
    azar = randDistContUnifLbUb(0, tope(numElem))
    i = 1
    'Búsqueda secuencial en los rangos de probabilidades
    While azar >= tope(i) And i < numElem
        i = i + 1
    Wend
    'Se podria implementar una busqueda binaria en el caso
    'de que numElem sea muy grande
    randDistDiscUser_d = dataSet(i)
End Function
Function randDistDiscUser_s(dataSet() As String, probSet() As Double) As String
    Dim azar As Double
    Dim i As Long
    Dim numElem As Long
    numElem = UBound(dataSet) - LBound(dataSet) + 1
    ReDim tope(1 To numElem) As Double
    If numElem = 1 Then
        randDistDiscUser_s = dataSet(1)
        Exit Function
    End If
    tope(1) = probSet(1)
    For i = 2 To numElem
        tope(i) = tope(i - 1) + probSet(i)
    Next i
    azar = randDistContUnifLbUb(0, tope(numElem))
    i = 1
    'Búsqueda secuencial en los rangos de probabilidades
    While azar >= tope(i) And i < numElem
        i = i + 1
    Wend
    'Se podria implementar una busqueda binaria en el caso
    'de que numElem sea muy grande
    randDistDiscUser_s = dataSet(i)
End Function
Function randDistDiscUser_l(dataSet() As Long, probSet() As Double) As Long
    Dim azar As Double
    Dim i As Long
    Dim numElem As Long
    numElem = UBound(dataSet) - LBound(dataSet) + 1
    ReDim tope(1 To numElem) As Double
    If numElem = 1 Then
        randDistDiscUser_l = dataSet(1)
        Exit Function
    End If
    tope(1) = probSet(1)
    For i = 2 To numElem
        tope(i) = tope(i - 1) + probSet(i)
    Next i
    azar = randDistContUnifLbUb(0, tope(numElem))
    i = 1
    'Búsqueda secuencial en los rangos de probabilidades
    While azar >= tope(i) And i < numElem
        i = i + 1
    Wend
    'Se podria implementar una busqueda binaria en el caso
    'de que numElem sea muy grande
    randDistDiscUser_l = dataSet(i)
End Function
Function randDistDiscUser_i(dataSet() As Integer, probSet() As Double) As Integer
    Dim azar As Double
    Dim i As Long
    Dim numElem As Long
    numElem = UBound(dataSet) - LBound(dataSet) + 1
    ReDim tope(1 To numElem) As Double
    If numElem = 1 Then
        randDistDiscUser_i = dataSet(1)
        Exit Function
    End If
    tope(1) = probSet(1)
    For i = 2 To numElem
        tope(i) = tope(i - 1) + probSet(i)
    Next i
    azar = randDistContUnifLbUb(0, tope(numElem))
    i = 1
    'Búsqueda secuencial en los rangos de probabilidades
    While azar >= tope(i) And i < numElem
        i = i + 1
    Wend
    'Se podria implementar una busqueda binaria en el caso
    'de que numElem sea muy grande
    randDistDiscUser_i = dataSet(i)
End Function
Function randDistContUnif01() As Double
'Devuelve un valor entre cero (incusive) y uno (exclusive)
'The Rnd function returns a value less than 1 but greater than or equal to zero.
'Before calling Rnd, use the Randomize statement without an argument to initialize the random-number generator with a seed based on the system timer.
'Rnd(number)
'Less than zero       The same number every time, using number as the seed.
'Greater than zero    The next random number in the sequence.
'Equal to zero        The most recently generated number.
'Not supplied         The next random number in the sequence.
'For any given initial seed, the same number sequence is generated because each successive call to the Rnd function uses the previous number as a seed for the next number in the sequence.

    Select Case tipo_funcion_azar_gcf
        Case CTE_AZARVB
            randDistContUnif01 = Rnd
        Case CTE_AZARFIC
            'Uso los CTE_NUM_DECIMALES_EXACTITUD_AZARFIC decimales de pi
            'a partir de cierta posición
            'y pongo un numero que es "0,esos decimales"
            Dim i As Integer
            randDistContUnif01 = 0
            For i = 1 To CTE_NUM_DECIMALES_EXACTITUD_AZARFIC
                randDistContUnif01 = randDistContUnif01 + (digitos_azar(indice_azar) / (10 ^ i))
                'Actualizo el indice que apunta al azar
                indice_azar = fl_SumCirc(azar_fichero_num_char_gcf, indice_azar, 1)
            Next i
            'Una vez ejecutado el bucle,
            'he saltado CTE_NUM_DECIMALES_EXACTITUD_AZARFIC digitos, los que he usado como decimales
        Case Else
            s_error_ger CTE_ERROR_GRAVE, "Generador de Pseudoaleatorios no existente"
    End Select
End Function
Function randDistContUnif1Ub(Ub As Double) As Double
    randDistContUnif1Ub = ((Ub - 1) * randDistContUnif01) + 1
End Function
Function randDistContNormMemLbUbMDt(Lb As Double, Ub As Double, M As Double, Dt As Double) As Double
    randDistContNormMemLbUbMDt = randDistContNormLbUbMDt(Lb, Ub, M, Dt)
End Function
Function randDistContUnifLbUb(Lb As Double, Ub As Double) As Double
    randDistContUnifLbUb = ((Ub - Lb) * randDistContUnif01) + Lb
End Function
Function randDistContNormLbUbMDt(Lb As Double, Ub As Double, M As Double, Dt As Double) As Double
    'Devuelve un numero al azar entre LI y LS
    'segun una distribución normal o gaussiana (es lo mismo)
    'con una cierta media y desviación tipica
    'con forma de campana de gauss
    'de forma que devuelve con mayor probabilidad valores
    'cercanos a la media que hemos fijado

    Dim suma_azar As Double
    Dim i As Integer
    Dim calidad As Integer
    Dim metodo As Integer
    Dim dispersion_uniforme_generadora As Double
    Dim media_uniforme_generadora As Double
    
    'Aqui aparecen programados varios metodos, pero
    'el usado es el llamado 1
    
    'Para metodo = 1
    metodo = 1
    calidad = 10
    dispersion_uniforme_generadora = Sqr(12 / calidad)
    media_uniforme_generadora = calidad / 2
    
    'Para metodo = 3
    Dim devolver As Double
    Dim valor1 As Double
    Dim valor2 As Double
    Dim factor As Double
    
    Select Case metodo
        Case 1
            'Metodo 1
            '=====================================================
            'Propuesto por Héctor Rodrigo
            'Teorema central del límite
            '=====================================================
            'Para obligar a unos limites tendre que hacer un bucle
            'que la llame constantemente hasta que caiga ahí
            'Esto calcula una normal entre -infinito e infinito
            randDistContNormLbUbMDt = Lb - 1
            While randDistContNormLbUbMDt < Lb Or randDistContNormLbUbMDt > Ub
                suma_azar = 0
                For i = 1 To calidad
                    suma_azar = suma_azar + randDistContUnif01
                    DoEvents
                Next i
                randDistContNormLbUbMDt = M + (Dt * dispersion_uniforme_generadora * (suma_azar - media_uniforme_generadora))
            Wend
            '=====================================================
        Case 2
            'Metodo 2
            '=====================================================
            'Propuesto por Phil Beffrey phil@pixar.com
            'y Mattias Fagerlund matfa@acacia.se
            'Calcular la media de varios numeros generados al azar con una distribucion uniforme
            'bastan unos 12 ejemplos
            'La media de una distribución uniforme tiende a una normal
            'El problema es como admitir distintas varianzas.
            'Se podria hacer que los numeros generados de forma uniforme
            'se generen con distintos limites inferior y superior
            'Si cada vez vamos reduciendo los limites, reducimos la dispersion
            'y si los ampliamos, la aumentamos. El problema es que no
            'sabemos cuanto!
            '=====================================================
            'Para obligar a unos limites tendre que hacer un bucle
            'que la llame constantemente hasta que caiga ahi
            randDistContNormLbUbMDt = Lb - 1
            While randDistContNormLbUbMDt < Lb Or randDistContNormLbUbMDt > Ub
                suma_azar = 0
                For i = 1 To calidad
                    suma_azar = suma_azar + randDistContUnifLbUb(Lb, Ub)
                Next i
                suma_azar = suma_azar / calidad
                randDistContNormLbUbMDt = suma_azar
            Wend
            '=====================================================
        Case 3
            'Metodo 3
            '===================================================
            'Obtenido de:
            'author = "William H. Press and Brian P. Flannery and Saul A. Teukolsky and William T. Vetterling",
            'Title = "{NUMERICAL RECIPES} The Art Of Scientific Computing ({FORTRAN}Version)"
            'publisher="Cambridge University Press"
            'Year = "1989"
            '(Existe tambien "NUMERICAL RECIPES IN C", de William H. Press, citado por Vensim)
            'Gracias a
            'Evan Hughes E.J.Hughes@rmcs.cranfield.ac.uk
            'http://www.rmcs.cranfield.ac.uk/~daps/daps/pgrads/e_h/hughes.htm
            '    suma = 0
            '    While suma = 0 Or suma >= 1
            '        valor1 = 2 * randDistContUnif01 - 1
            '        valor2 = 2 * randDistContUnif01 - 1
            '        suma = valor1 * valor1 + valor2 * valor2
            '    Wend
            '    factor = sigma * sqrt(-2 * Log(suma) / suma)
            '    solucion1 = valor1 * factor + media
            '    solucion2 = valor2 * factor + media
            '
            '===================================================
            'Posibles errores al traducir de C
            'Supongo que rand() devuelve entre 0 y RAND_MAX pero no se incluye el 0 ni el RAND_MAX
            'Supongo que sqrt es identico a sqr de VB
            'U1 = rand() / RAND_MAX
            'U2 = rand() / RAND_MAX
            'x1=2*(double)rand()/RAND_MAX-1;
            'x2=2*(double)rand()/RAND_MAX-1;
            'La media es 0
            'y la desviacion tipica o sigma es 1
            'Obtenido de Box-Muller method
            'gracias a Antonio Carpintero Sanchez amcarpintero@polar.es
            '=====================================================
            'Para obligar a unos limites tendre que hacer un bucle
            'que la llame constantemente hasta que caiga ahi
            randDistContNormLbUbMDt = Lb - 1
            While randDistContNormLbUbMDt < Lb Or randDistContNormLbUbMDt > Ub
                If hay_solucion_anterior_gauss Then
                    devolver = solucion_anterior_gauss
                Else
                    suma_azar = 1
                    While suma_azar >= 1
                        valor1 = 2 * randDistContUnif01 - 1
                        valor2 = 2 * randDistContUnif01 - 1
                        suma_azar = valor1 * valor1 + valor2 * valor2
                    Wend
                    factor = Dt * Sqr(-2 * Log(suma_azar) / suma_azar)
                    devolver = valor1 * factor + M
                    solucion_anterior_gauss = valor2 * factor + M
                End If
                hay_solucion_anterior_gauss = Not hay_solucion_anterior_gauss
                randDistContNormLbUbMDt = devolver
    
            Wend
            '=====================================================
    End Select
    
End Function
Function randDistDiscCantorUnifLbUb(Lb As Double, Ub As Double, stepSet() As Double, probSet() As Double) As Double
    Dim azar As Double
    'Sacamos un valor al azar con el maximo nivel de detalle
    'segun una función uniforme
    azar = randDistContUnifLbUb(Lb, Ub)
    'Ahora se discretiza ese valor segun el step indicado
    'elegido segun esas probabilidades
    'Por ejemplo
    'stepSet(1) = 1
    'stepSet(2) = 0.1
    'stepSet(3) = 0.01
    'probSet(1) = 50
    'probSet(2) = 40
    'probSet(3) = 10
    randDistDiscCantorUnifLbUb = cont2disc(azar, randDistDiscUser_d(stepSet(), probSet()))
End Function
Function randDistDiscCantorNormLbUbMDt(Lb As Double, Ub As Double, M As Double, Dt As Double, stepSet() As Double, probSet() As Double) As Double
    Dim azar As Double
    'Sacamos un valor al azar con el maximo nivel de detalle
    'segun una función normal
    azar = randDistContNormLbUbMDt(Lb, Ub, M, Dt)
    'Ahora se discretiza ese valor segun el step indicado
    'elegido segun esas probabilidades
    'Por ejemplo
    'stepSet(1) = 1
    'stepSet(2) = 0.1
    'stepSet(3) = 0.01
    'probSet(1) = 50
    'probSet(2) = 40
    'probSet(3) = 10
    randDistDiscCantorNormLbUbMDt = cont2disc(azar, randDistDiscUser_d(stepSet(), probSet()))
End Function

