Spanish Error extraño con variable de tipo Float. [SOLUCIONADO]

carlos7000

Active Member
Licensed User
Hola a todos.

Estoy escribiendo un sencillo programa el cual lo único que tiene que hacer es sumar el numero 0.000000000000001, un numero dado de veces.

Al decirle que realice ciclos con valores pequeños, el programa funciona bien, por ejemplo que sume el numero antes dado, 5000 veces, el resultado es 0.000000000005000 correcto! Pero al darle el numero 50000 el resultado es 0.000000000049973


Al probar el mimo codigo en un computador de escritorio se presenta el mismo error

Este es el código B4A que da el error mencionado:

B4X:
Sub Test
    Try
        ButtonRun.Enabled = False
        Dim Inicio, Final As Long
        Dim Ciclos As Int
    
        Ciclos = EditText1.Text
 
        Dim Total As Float
        Total = 0
 
        Inicio = DateTime.Now
        Do While Ciclos > 0
            Ciclos = Ciclos - 1
            Total = Total + 0.000000000000001
        Loop
        Final = DateTime.Now
 
        LabelCalculos.Text = NumberFormat2(Total, 1, 15, 15, False)
        LabelTiempo.Text = Final - Inicio
    
        ButtonRun.Enabled = True
    Catch
        Log(LastException)
    End Try
End Sub
También adjunto el proyecto completo en .Zip (Prueba 1.zip)

Este es el código B4J que en un computador de escritorio presenta el mismo error

B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private TextFieldNombre As TextField
    Private ButtonSaludar As Button
    Private LabelMuestraSaludo As Label
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.WindowHeight= 150
    MainForm.WindowWidth = 475 'Ancho
    MainForm.Show
    LabelMuestraSaludo.Text = ""
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub ButtonSaludar_Click   
    Calcular (TextFieldNombre.Text)
End Sub

Sub Calcular (Ciclos As Int)
    Dim Total As Float
    
    Total = 0
    
    Do While Ciclos > 0
        Ciclos = Ciclos - 1
        Total = Total + 0.000000000000001
    Loop
    
    fx.Msgbox(MainForm, NumberFormat(Total, 1, 15), "Resultado")
End Sub
Adjunto también el proyecto completo en B4J (Proyecto en B4J.zip)
 

Attachments

Last edited:

Gustsp

Member
Licensed User
Hola a todos.

Estoy escribiendo un sencillo programa el cual lo único que tiene que hacer es sumar el numero 0.000000000000001, un numero dado de veces.

Al decirle que realice ciclos con valores pequeños, el programa funciona bien, por ejemplo que sume el numero antes dado, 5000 veces, el resultado es 0.000000000005000 correcto! Pero al darle el numero 50000 el resultado es 0.000000000049973


Al probar el mimo codigo en un computador de escritorio se presenta el mismo error

Este es el código B4A que da el error mencionado:

B4X:
Sub Test
    Try
        ButtonRun.Enabled = False
        Dim Inicio, Final As Long
        Dim Ciclos As Int
   
        Ciclos = EditText1.Text
 
        Dim Total As Float
        Total = 0
 
        Inicio = DateTime.Now
        Do While Ciclos > 0
            Ciclos = Ciclos - 1
            Total = Total + 0.000000000000001
        Loop
        Final = DateTime.Now
 
        LabelCalculos.Text = NumberFormat2(Total, 1, 15, 15, False)
        LabelTiempo.Text = Final - Inicio
   
        ButtonRun.Enabled = True
    Catch
        Log(LastException)
    End Try
End Sub
También adjunto el proyecto completo en .Zip (Prueba 1.zip)

Este es el código B4J que en un computador de escritorio presenta el mismo error

B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private TextFieldNombre As TextField
    Private ButtonSaludar As Button
    Private LabelMuestraSaludo As Label
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.WindowHeight= 150
    MainForm.WindowWidth = 475 'Ancho
    MainForm.Show
    LabelMuestraSaludo.Text = ""
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub ButtonSaludar_Click  
    Calcular (TextFieldNombre.Text)
End Sub

Sub Calcular (Ciclos As Int)
    Dim Total As Float
   
    Total = 0
   
    Do While Ciclos > 0
        Ciclos = Ciclos - 1
        Total = Total + 0.000000000000001
    Loop
   
    fx.Msgbox(MainForm, NumberFormat(Total, 1, 15), "Resultado")
End Sub
Adjunto también el proyecto completo en B4J (Proyecto en B4J.zip)
Buenas @carlos7000
No es algo del lenguaje, es mas bien algo que esta es la verdadera naturaleza del punto flotante binario: no es un error de B4A, y tampoco es un error en tu código. Verás lo mismo en todos los lenguajes que soportan la aritmética de punto flotante
https://www.google.com/search?&q=error+de+coma+flotante&oq=error+coma+flotante
hasta en el excel
https://support.microsoft.com/es-do...ithmetic-may-give-inaccurate-results-in-excel
 

carlos7000

Active Member
Licensed User
Buenas @carlos7000
No es algo del lenguaje, es mas bien algo que esta es la verdadera naturaleza del punto flotante binario: no es un error de B4A, y tampoco es un error en tu código. Verás lo mismo en todos los lenguajes que soportan la aritmética de punto flotante
https://www.google.com/search?&q=error+de+coma+flotante&oq=error+coma+flotante
hasta en el excel
https://support.microsoft.com/es-do...ithmetic-may-give-inaccurate-results-in-excel
Hola.

¿Y entonces?

¿Es posible hacer este programa? Si es así, ¿Como?

Gracias por su respuesta.
 

carlos7000

Active Member
Licensed User
Modifique la función Test, la nueva función es:

B4X:
Sub Test
    Try
        ButtonRun.Enabled = False
        Dim Inicio As Long
        Dim Final As Long
        Dim Ciclos As Int
       
        Ciclos = EditText1.Text
   
        Dim Total As Float
        Total = 0
   
        Inicio = DateTime.Now
        Do While Ciclos > 0
            Ciclos = Ciclos - 1
            Total = Total + 0.000001
        Loop       
        Final = DateTime.Now
   
        LabelCalculos.Text = NumberFormat2(Total, 1, 15, 15, False)       
        LabelTiempo.Text = Final - Inicio
       
        ButtonRun.Enabled = True
    Catch
        Log(LastException)
    End Try
End Sub
La precisión requerida es menor, pero el error persiste.

Se supone que el valor obtenido debería ser 0.05 pero el resultado del computo es 0.049974355846643
 

Gustsp

Member
Licensed User
Modifique la función Test, la nueva función es:

B4X:
Sub Test
    Try
        ButtonRun.Enabled = False
        Dim Inicio As Long
        Dim Final As Long
        Dim Ciclos As Int
      
        Ciclos = EditText1.Text
  
        Dim Total As Float
        Total = 0
  
        Inicio = DateTime.Now
        Do While Ciclos > 0
            Ciclos = Ciclos - 1
            Total = Total + 0.000001
        Loop      
        Final = DateTime.Now
  
        LabelCalculos.Text = NumberFormat2(Total, 1, 15, 15, False)      
        LabelTiempo.Text = Final - Inicio
      
        ButtonRun.Enabled = True
    Catch
        Log(LastException)
    End Try
End Sub
La precisión requerida es menor, pero el error persiste.

Se supone que el valor obtenido debería ser 0.05 pero el resultado del computo es 0.049974355846643
Prueba a cambiar la declaracion para obtener una mayor precisión.
B4X:
Dim Total As Double
 

José J. Aguilar

Well-Known Member
Licensed User
Hola Carlos7000:

Supongo (esto no lo digo como experto, sino lo que recuerdo de cálculo infinitesimal) que no es que Float no sirva, sino que es un problema de precisión, y por tanto cualquier pequeña falta de precisión en el cálculo, se va arrastrando en cada suma.

saludos,
 
Top