0

I am looking for a correct implement of dot product using mpmath, but they give me different results, which I don't understand why.

sum = mp.mpf(0.)                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                          
for i in range(n):                                                                                                                                                                                                                                    
         sum +=  mp.mpf(x[i]) * mp.mpf(y[i])            # 1st method                                                                                                                                                                                                      
#        sum +=  mp.mpf(str(x[i])) * mp.mpf(str(y[i]))  # 2nd mehtod

I am using them to solve ill-conditioned dot products and the two give very different results. This is very important because I am comparing them with my another accurate dot product algorithm, which agrees with the 1st method , and disagree with the 2nd method. So I want to understand if I should trust the answer from the 1st.

2 Answers2

1

Whether you should trust answer from the 1st depend on the precision, and accumulation of numerical error. But at least, that is the correct way.

The second method (besides being convoluted and expansive: it forces the creation of a human readable string, which is normally only for humans to read, and then parse it again, which is normally only for trying to understand numbers given by humans. I know I am saying this like if I were asking "why robots in Star Wars speak to each other in English when they surely have more efficient robot languages", but really, it is just about the unnecessary cost of printing and parsing strings), the second method loose accuracy. Because str shows only digits it is sure about. So, for example

mp.mp.dps=5
a=mp.mpf(1)
b=mp.mp2(3)
a/b
# 0.33333349
str(a/b)
# 0.33333

As you can see, we loose the 3 last digits 349. The 3 is a serious loss. But even the 49 is: sure, digits are not really 49 in the real value of 1/3, but they aren't 00 neither, and correct value is closer to 49 that to 00

Still, it is a good idea for str (and printing functions) to show only correct digits (the 5 digits of precision I've asked for). But only because they are used not for computation but for printing. So that is another reason for my initial rant on "don't use human/machine function for machine/machine computation": not only, as I said, that is unnecessary work, but also, humans want to see true digits, when machines want to play with all information present, even the one with some error is still better that nothing.

chrslg
  • 9,023
  • 5
  • 17
  • 31
  • Thanks for the answer. if the 1st method depends on precision, should I declare my array x = mp.mpf(1.232039290796878091253424824196e-04) or x = mp.mpf('1.232039290796878091253424824196e-04') to keep the precision? – WhatsupAndThanks Jun 25 '23 at 05:32
  • 1
    That is a case of "human interaction". You need the string in this case, since it is for inputting the number. Problem here is not from `mpfr` itself. Problem is that there is no such thing as `1.232039290796878091253424824196e-04` in python. This even even the reason why you are using `mpfr` in the first place. `"1.232039290796878091253424824196e-04"` is a thing in python. `1.232039290796878091253424824196e-04` isn't. (Or, to be more precise, it is just an unnecessarily long alternate name for `0.0001232039290796878`). – chrslg Jun 25 '23 at 13:29
  • Note that the situation is not the same as for `mpfr(x)` vs `mpfr(str(x))` of your initial question. In thes case of your initial question, `x` is already a `mpf`. You are not trying to input it through python numbers whose precision cannot hold enough digits. – chrslg Jun 25 '23 at 13:32
  • So, in short, when you type a number, with many digits, to create a `mpf` with, you should put those digits into a string, or else many will be lost in the short time they are considered a classical python number. But when `mpfr` passes a number to another `mpfr`, there is no reason to convert them to string then back to `mpfr`: they are already `mpf`, holding all the digits. python native number type is not involved here. – chrslg Jun 25 '23 at 13:35
1

you shouldn't use str()

Instead, you should use mp.nstr(x,n), where n is the significant digits,aka, the number of digits you cares.

also, as mentioned by @chrsig , method 1 will be the most accurate.

Leo
  • 11
  • 3