niels
niels

Reputation: 760

Conversion of numeric to string in MATLAB

Suppose I want to conver the number 0.011124325465476454 to string in MATLAB.

If I hit

mat2str(0.011124325465476454,100)

I get 0.011124325465476453 which differs in the last digit.

If I hit num2str(0.011124325465476454,'%5.25f')

I get 0.0111243254654764530000000

which is padded with undesirable zeros and differs in the last digit (3 should be 4).

I need a way to convert numerics with random number of decimals to their EXACT string matches (no zeros padded, no final digit modification).

Is there such as way?

EDIT: Since I din't have in mind the info about precision that Amro and nrz provided, I am adding some more additional info about the problem. The numbers I actually need to convert come from a C++ program that outputs them to a txt file and they are all of the C++ double type. [NOTE: The part that inputs the numbers from the txt file to MATLAB is not coded by me and I'm actually not allowed to modify it to keep the numbers as strings without converting them to numerics. I only have access to this code's "output" which is the numerics I'd like to convert]. So far I haven't gotten numbers with more than 17 decimals (NOTE: consequently the example provided above, with 18 decimals, is not very indicative).

Now, if the number has 15 digits eg 0.280783055069002

then num2str(0.280783055069002,'%5.17f') or mat2str(0.280783055069002,17) returns

0.28078305506900197

which is not the exact number (see last digits).

But if I hit mat2str(0.280783055069002,15) I get

0.280783055069002 which is correct!!!

Probably there a million ways to "code around" the problem (eg create a routine that does the conversion), but isn't there some way using the standard built-in MATLAB's to get desirable results when I input a number with random number of decimals (but no more than 17);

Upvotes: 3

Views: 8898

Answers (4)

KAlO2
KAlO2

Reputation: 888

You cannot get EXACT string since the number is stored in double type, or even long double type. The number stored will be a subtle more or less than the number you gives.

computer only knows binary number 0 & 1. You must know that numbers in one radix may not expressed the same in other radix. For example, number 1/3, radix 10 yields 0.33333333...(The ellipsis (three dots) indicate that there would still be more digits to come, here is digit 3), and it will be truncated to 0.333333; radix 3 yields 0.10000000, see, no more or less, exactly the amount; radix 2 yields 0.01010101... , so it will likely truncated to 0.01010101 in computer,that's 85/256, less than 1/3 by rounding, and next time you fetch the number, it won't be the same you want.

So from the beginning, you should store the number in string instead of float type, otherwise it will lose precision.

Considering the precision problem, MATLAB provides symbolic computation to arbitrary precision.

Upvotes: 0

Amro
Amro

Reputation: 124563

That's because your number is beyond the precision of the double numeric type (it gives you between 15 to 17 significant decimal digits). In your case, it is rounded to the nearest representable number as soon as the literal is evaluated.

If you need more precision than what the double-precision floating-points provides, store the numbers in strings, or use arbitrary-precision libraries. For example use the Symbolic Toolbox:

sym('0.0111243254654764549999999')

Upvotes: 0

user85109
user85109

Reputation:

My HPF toolbox also allows you to work with an arbitrary precision of numbers in MATLAB.

In MATLAB, try this:

>> format long g
>> x = 0.280783054
x =
               0.280783054

As you can see, MATLAB writes it out with the digits you have posed. But how does MATLAB really "feel" about that number? What does it store internally? See what sprintf says:

>> sprintf('%.60f',x)
ans =
0.280783053999999976380053112734458409249782562255859375000000

And this is what HPF sees, when it tries to extract that number from the double:

>> hpf(x,60)
ans =
0.280783053999999976380053112734458409249782562255859375000000

The fact is, almost all decimal numbers are NOT representable exactly in floating point arithmetic as a double. (0.5 or 0.375 are exceptions to that rule, for obvious reasons.)

However, when stored in a decimal form with 18 digits, we see that HPF did not need to store the number as a binary approximation to the decimal form.

x = hpf('0.280783054',[18 0])
x =
0.280783054

>> x.mantissa
ans =
  2 8 0 7 8 3 0 5 4 0 0 0 0 0 0 0 0 0

What niels does not appreciate is that decimal numbers are not stored in decimal form as a double. For example what does 0.1 look like internally?

>> sprintf('%.60f',0.1)
ans =
0.100000000000000005551115123125782702118158340454101562500000

As you see, matlab does not store it as 0.1. In fact, matlab stores 0.1 as a binary number, here in effect...

1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + ...

or if you prefer

2^-4 + 2^-5 + 2^-8 + 2^-9 + 2^-12 + 2^13 + 2^-16 + ...

To represent 0.1 exactly, this would take infinitely many such terms since 0.1 is a repeating number in binary. MATLAB stops at 52 bits. Just like 2/3 = 0.6666666666... as a decimal, 0.1 is stored only as an approximation as a double.

This is why your problem really is completely about precision and the binary form that a double comprises.

As a final edit after chat...

The point is that MATLAB uses a double to represent a number. So it will take in a number with up to 15 decimal digits and be able to spew them out with the proper format setting.

>> format long g
>> eps 
ans = 
2.22044604925031e-16

So for example...

>> x = 1.23456789012345
x =
          1.23456789012345

And we see that MATLAB has gotten it right. But now add one more digit to the end.

>> x = 1.234567890123456
x =
          1.23456789012346

In its full glory, look at x, as MATLAB sees it:

>> sprintf('%.60f',x)
ans =
1.234567890123456024298320699017494916915893554687500000000000

So always beware the last digit of any floating point number. MATLAB will try to round things intelligently, but 15 digits is just on the edge of where you are safe.

Is it necessary to use a tool like HPF or MP to solve such a problem? No, as long as you recognize the limitations of a double. However tools that offer arbitrary precision give you the ability to be more flexible when you need it. For example, HPF offers the use and control of guard digits down in that basement area. If you need them, they are there to save the digits you need from corruption.

Upvotes: 4

nrz
nrz

Reputation: 10560

You can use Multiple Precision Toolkit from MATLAB File Exchange for arbitrary precision numbers. Floating point numbers do not usually have a precise base-10 presentation.

Upvotes: 0

Related Questions