I'm just looking for two functions, f
from double
to string
and g
from string
to double
, such that g(f(d)) == d
for any double d
(scalar and real double
).
How do I convert a double
to a string
or char
array in a reversible way? I mean, in such a way that afterward I can convert that string
/char
array back to double
retrieving the original result.
I've found formattedDisplayText
, and in some situations it works:
>> x = eps
x =
2.220446049250313e-16
>> double(formattedDisplayText(x, 'NumericFormat', 'long')) - x
ans =
0
But in others it doesn't
x = rand(1)
x =
0.546881519204984
>> double(formattedDisplayText(x, 'NumericFormat', 'long')) - x
ans =
1.110223024625157e-16
As regards this and other tools like num2str
, mat2str
, at the end they all require me to decide a precision, whereas I would like to express the idea of "use whatever precision is needed for you (MATLAB) to be able to read back your own number".
X = str2double( str ) converts the text in str to double precision values. str contains text that represents real or complex numeric values. str can be a character vector, a cell array of character vectors, or a string array. If str is a character vector or string scalar, then X is a numeric scalar.
Description. The atof() function converts a character string to a double-precision floating-point value.
str = string( A ) converts the input array to a string array. For instance, if A is numeric vector [1 20 300] , str is a string array of the same size, ["1" "20" "300"] . str = string( A , dateFmt ) , where A is a datetime or duration array, applies the specified format, such as "HH:mm:ss" .
Here are two simpler solutions to convert a single double value to a string and back without loss.
Use num2str
to obtain 17 decimal digits in string form, and str2double
to convert back:
>> s = mat2str(x,17)
s =
'2.2204460492503131e-16'
>> y = str2double(s);
>> y==x
ans =
logical
1
Note that 17 digits are always enough to represent any IEEE double-precision floating-point number.
Use matlab.net.base64encode
to encode the 8 bytes of the number. Unfortunately you can only encode strings and integer arrays, so we type cast to some integer array (we use uint8
here, but uint64
would work too). We reverse the process to get the same double value back:
>> s = matlab.net.base64encode(typecast(x,'uint8'))
s =
'AAAAAAAAsDw='
>> y = typecast(matlab.net.base64decode(s),'double');
>> x==y
ans =
logical
1
Base64 encodes every 3 bytes in 4 characters, this is the most compact representation you can easily create. A more complex algorithm could likely convert into a smaller UTF-8-encoded string (which uses more than 6 bytes per displayable character).
f
: from double real-valued scalar x
to char vector str
str = num2str(typecast(x, 'uint8'));
str
is built as a string containing 8 numbers, which correspond to the bytes in the internal representation of x
. The function typecast
extracts the bytes as a numerical vector, and num2str
converts to a char vector with numbers separated by spaces.
g
: from char vector str
to double real-valued scalar y
y = typecast(uint8(str2double(strsplit(str))), 'double');
The char vector is split at spaces using strsplit
. The result is a cell array of char vectors, each of which is then interpreted as a number by str2double
, which produces a numerical vector. The numbers are cast to uint8
and then typecast
interprets them as the internal representation of a double real-valued scalar.
Note that str2double(strsplit(str))
is preferred over the simpler str2num(str)
, because str2num
internally calls eval
, which is considered evil bad practice.
>> format long
>> x = sqrt(pi)
x =
1.772453850905516
>> str = num2str(typecast(x, 'uint8'))
str =
'106 239 180 145 248 91 252 63'
>> y = typecast(uint8(str2double(strsplit(str))), 'double')
y =
1.772453850905516
>> x==y
ans =
logical
1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With