How to work with super accurate Python values?

Asked

Viewed 84 times

0

I’m creating an algorithm and I’m encountering a strange problem, I have a set of precise values and an unknown goal, basically a neural network. I used several tactics to optimize weights and now I’ve made an algorithm to try to find the best values in brute force. The algorithm transforms the value of a single weight into a string and changes an individual value of that string, thus:

0.9922788982003661
0.9922798982003661
0.9922720982003661
0.992272198200366
0.9922722982003661
0.9922723982003661
0.9922724982003661
0.9922725982003661
0.9922726982003661
0.9922727982003661

Each time this happens, I convert the string to float and run the neural network, capturing the accuracy of the network with the weights, however, as we see in the marked line, the number 1 at the end was suppressed without any cause, apparently there is a bug in the function "float" that may or may not fade with the ultimate value when it comes to that precision.

I did this test to demonstrate the anomaly, first the string and then the converted value:

strin 0.9922728982001661
float 0.9922728982001661

strin 0.9922728982002661
float 0.9922728982002661

strin 0.9922728982003661
float 0.9922728982003661

strin 0.9922728982004661
float 0.992272898200466

strin 0.9922728982005661
float 0.9922728982005661

When I work with low precision, this problem does not appear:

strin 1.023
float 1.023

strin 1.123
float 1.123

strin 1.223
float 1.223

strin 1.323
float 1.323

strin 1.423
float 1.423

strin 1.523
float 1.523

strin 1.623
float 1.623

strin 1.723
float 1.723

strin 1.823
float 1.823

strin 1.923
float 1.923

strin 1.103
float 1.103

strin 1.113
float 1.113

strin 1.123
float 1.123

strin 1.133
float 1.133

strin 1.143
float 1.143

strin 1.153
float 1.153

strin 1.163
float 1.163

strin 1.173
float 1.173

strin 1.183
float 1.183

strin 1.193
float 1.193

strin 1.120
float 1.12

strin 1.121
float 1.121

strin 1.122
float 1.122

strin 1.123
float 1.123

strin 1.124
float 1.124

strin 1.125
float 1.125

strin 1.126
float 1.126

strin 1.127
float 1.127

strin 1.128
float 1.128

strin 1.129
float 1.129

The only difference between the values is the float.

for valor in range(0,10):

    listaCaracteres = listaCaracteres[:nchar] + str(valor) + listaCaracteres[nchar + 1:]
    finalCaracteres = decimal + '.' + listaCaracteres

    print('strin',finalCaracteres)
    print('float',float(finalCaracteres))

Unfortunately, this is getting in the way of the algorithm, do you have any idea how to maintain accuracy by converting the string to float without this "bug"? (Warning that the value comes in float, is converted to string, undergoes change and is converted to float again, and this problem always happens in the last character, only when I work with this precision, tests with 4 houses for example, everything happens correctly )

I’m using Ubuntu 19.10 with this version of Python:
3.7.5 (default, Nov 20 2019, 09:21:52) [GCC 9.2.1 20191008]

  • 2

    maybe using the Decimal class in the decimal module can solve this problem

  • Ual, this library is fantastic, solved my problem, thank you very much @Eltonnunes

  • The work-Around for this in Python is to use decimal. Decimal - but if this is your profession you DEFINITELY need to understand about floating point numbers and how they are handled by harware - I suggest starting here: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

  • PS. Decimal in Python can work with a preselected arbitrary precision, but that’s hundreds of times slower than working with hardware floating point clusters - which has the above limit (and that’s not something specific to Python, acotnece in any language) - then you have to visit your problem and see if it has how to be computed with numbers pontof lutuante with loss, or emulated with integers- or, depending on the case, use Arbirtratian decimals even with the slowness that they have.

  • The link above I think is too academic - and very mathematical - I think this article is more relaxed to start: https://www.phys.uconn.edu/~Rozman/Courses/P2200_15F/downloads/floating-point-guide-2015-10-15.pdf

1 answer

0

As the computer has only work with binary operations the decimal values have a certain maximum precision after a certain point the value is arbritario of the nearest value that the binary operation has managed to perform.

One way out is you turn all numbers into integers and work with them and then format them to the floating point again

Pseudo Code Example

#Considerando um numero com 11 casas decimais
x = 0.12390128390
print(x)
#>> 0.1239012839
#Transformo em inteiro
conv_x  = x*(10**11)
conv_x
print(conv_x)
# >> 12390128390.0
#Faço alguma operação lembrando que devem manter a mesma base
operacao = conv_x + (0.00001*(10**11))
print(operacao)
# >> 12391128390.0

#diferença
print(operacao - conv_x)
#>> 1000000.0

#Reconverto para a ponto flutuante
ponto_flutuante = operacao * (10**-11)
print(ponto_flutuante)
#>> 0.12391128389999999

#note que o valor ja foi arredondado neste caso o ideal é salvar 
# o valor multiplicado por um expoente X e se necessario converter novamente
# salve o resultado como texto para não acontecer arredondamentos

ponto_flu_str =  "0." + str(int(operacao))
print(ponto_flu_str)
#>> 0.12391128390



Browser other questions tagged

You are not signed in. Login or sign up in order to post.