필터 지우기
필터 지우기

I want to do this:2.389​8769657358​3658648235​686+5.6387​6498376982​3768764987​9932 and i need all digits,vpa dosen't work properly.Is there any function to do it?

조회 수: 2 (최근 30일)
for a certain calculation I need at least 40 digits precision.I used vpa but look:
vpa(0.123456789123456789123456789) ans = 0.12345678912345678379658409085096 it changes the value of number I entered, which leads to incorrect results.is there any way to this.I want to do 2.38987696573583658648235686+5.6387649837698237687649879932.how can I do it?
  댓글 수: 2
meh hadi
meh hadi 2018년 4월 21일
편집: meh hadi 2018년 4월 21일
Thanks.it worker but I want put the result in another variable and again use that variable.is there any function that can do this: a=function(2.45); a= '2.45' ?
Ameer Hamza
Ameer Hamza 2018년 4월 21일

One way is to define the starting number yourself. Once you get the result, you can convert the answer to char array using

char(vpa(first_number) + vpa(second_number))

Subsequently, you can easily use vpa() and char() to convert between two formats.

댓글을 달려면 로그인하십시오.

채택된 답변

John D'Errico
John D'Errico 2018년 4월 21일
편집: John D'Errico 2018년 4월 21일

First, when you do this:

vpa(0.123456789123456789123456789)

MATLAB stores the input to VPA as a DOUBLE. MATLAB does all computations using doubles, stores all numbers by default as doubles. The symbolic toolbox is different. But MATLAB itself works on doubles.

So as far as MATLAB is concerned,

0.123456789123456789123456789

is just a number, a double precision number. And doubles are stored in a binary form, with 52 bits of precision in the mantissa. So, while you gave MATLAB a number with lots of decimal digits, only about the first 16 of them will be stored correctly. The rest have now been lost, thrown into the bit bucket.

sprintf('%0.55f',0.123456789123456789123456789)
ans =
  '0.1234567891234567837965840908509562723338603973388671875'

VPA is just a function. MATLAB does not know what you will do with any number. It stores it temporarily in a double, then passes the results to the function being called, in this case, VPA.

Of course, VPA takes the number, and sees a DOUBLE. All it sees is what it was passed. It sees that binary representation, and converts those binary bits into a number. So, this is actually what VPA sees:

sprintf('%0.55f',0.123456789123456789123456789)
ans =
  '0.1234567891234567837965840908509562723338603973388671875'

So, if I ask for at least 55 digits for VPA, I'll get the complete number stored.

vpa(0.123456789123456789123456789,55)
ans =
0.1234567891234567837965840908509562723338603973388671875

By the way, you get those extra digits because binary fractions essentially gain an extra digit each time you divide by 2. So the first few powers of 1/2 are:

1 ./ 2.^(0:10)'
ans =
                       1
                     0.5
                    0.25
                   0.125
                  0.0625
                 0.03125
                0.015625
               0.0078125
              0.00390625
             0.001953125
            0.0009765625

Remember, the mantissa of a double has 52 binary bits in it. While some binary fractions can be stored exactly, like 1/2 and 1/4, most decimals are not stored exactly as decimals.

Now, VPA is SOMETIMES a bit smarter than you might think. It can recognize some numbers even when they have been converted to approximate doubles.

x = 1/3
x =
        0.333333333333333
sprintf('%0.55f',x)
ans =
    '0.3333333333333333148296162562473909929394721984863281250'
vpa(x,55)
ans =
0.3333333333333333333333333333333333333333333333333333333

But, for the most part, VPA is pretty dumb. It takes what it has been passed. And MATLAB is not smarter than that, because it works in terms of doubles by default.

Ok, so you CANNOT pass in a number as a double in general to VPA, and expect it to get things right. But you can pass in the number as a string.

digits 40
vpa('0.123456789123456789123456789')
ans =
0.123456789123456789123456789

Once MATLAB understands that you entered that number into symbolic form, it has no problem. It stores it in high precision form.

digits 40
x = vpa('2.38987696573583658648235686');
y = vpa('5.6387649837698237687649879932');
x + y
ans =
8.0286419495056603552473448532

Once x and y are symbolic numbers, they will stay as such.

exp(x)*y^2
ans =
346.9591673851377328054605380636824962144

So you are now working in 40 digits of precision. Computations will be a lot slower of course, but you cannot expect everything.

I would note that you could have done exactly the same thing using my HPF toolbox, found on the file exchange, but the symbolic toolbox is entirely sufficient here.

추가 답변 (1개)

Ameer Hamza
Ameer Hamza 2018년 4월 21일
편집: Ameer Hamza 2018년 4월 21일

You can first convert these numbers to char array or string and then apply vpa as follow

digits(40)
first_number = '2.38987696573583658648235686';
second_number = '5.6387649837698237687649879932';
result = vpa(first_number) + vpa(second_number)

This way you will not lose precision.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by