How to convert double to vpa?

5 views (last 30 days)
Robert Gray
Robert Gray on 12 Jan 2014
Edited: John D'Errico on 12 Jan 2014
I read in a number into variable hld. When I have Matlab display hld, setting format long, it displays hld =
-1.194776119402985e+02
This is correct based on the text -119.47761194029852000000 that I read in.
I want to do some vpa calculations, as I convert this number to a vpa type by
locX = vpa(hld);
When I display variable locX Matlab prints (I'll truncate the number)
-119.47761194029850746268656716417910447761194029850 ....
Where are all the "extra" non-zero digits coming from? Shouldn't it display
-119.47761194029850000000000000000000000000000000000 ... ? Or just
-119.4776119402985
What it is doing means that the number in vpa format is unreliable for my calculations. I need the number to be exactly
-119.4776119402985
So, is there a correct way to convert a double into a vpa?
I have many other places in the code where I do similar conversion from double to vpa. If they are all similarly random digits after the 14th decimal position, I'm in big trouble....
Cheers, Bob Gray

Answers (1)

John D'Errico
John D'Errico on 12 Jan 2014
Edited: John D'Errico on 12 Jan 2014
You are probably in big trouble then. Once you create a double from it, the number actually DOES implicitly have those crap digits past the 15th decimal place. You need to understand that MATLAB is an interpreted language. When you write something like
x = -119.4776119402985;
then MATLAB stores the number as a double. When you do the similar operation
x = vpa(-119.4776119402985);
MATLAB internally sees the number -119.4776119402985, converts it to a double, and ONLY THEN looks to see what to do with that number. This is how interpreted languages work, because otherwise the interpreter would need to be intelligent enough to know what you will do with those numbers in future lines of code, reading your mind as to what it SHOULD do, rather than what you TOLD it to do! Sorry, but computers simply are not that smart yet. (Honestly, I fear the day when they are that smart.)
A double number actually is stored in binary form internally. It is NOT stored in a decimal form. The correct way to create the symbolic number -119.4776119402985 is to create it in a symbolic form.
So this will work as you desire...
>> vpa(sym('-119.4776119402985'))
ans =
-119.4776119402985
Of course, if your need is simply to do high precision floating point arithmetic, you can also use my HPF toolbox. Using that toolbox, I'll show the difference in what you have done.
>> hpf('-119.4776119402985',100)
ans =
-119.4776119402985
>> hpf(-119.4776119402985,100)
ans =
-119.4776119402985017359242192469537258148193359375
See that the second form allows MATLAB to implicitly create the number as a double, which is ONLY THEN passed into HPF. Once that happens, your number has been "corrupted" into a binary form that approximates your number as closely as possible.
To understand why this happens, suppose you were asked to store the number 0.1 in a binary form, but using only a limited number of binary bits of information? The fact is, it is impossible to store that decimal number exactly in binary, regardless of how many bits you use.
Thus, with 3 bits, you might store it as 0.125. With 5 binary bits, 0.09375 is the best approximation. With 7 binary bits, it looks like I can get as close as 0.1015625. With 52 bits, it looks like we can come no closer than 0.1000000000000000055511151231257827021181583404541015625.
Welcome to the sometimes topsy, turvy world of floating point arithmetic, where the rules of mathematics don't always work as you would like.

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!