str2double --> double

Jan Studnicka on 14 Aug 2025
Latest activity Reply by WANG Zi-Xiang on 28 Nov 2025 at 0:26

Did you know that function double with string vector input significantly outperforms str2double with the same input:
x = rand(1,50000);
t = string(x);
tic; str2double(t); toc
Elapsed time is 0.276966 seconds.
tic; I1 = str2double(t); toc
Elapsed time is 0.244074 seconds.
tic; I2 = double(t); toc
Elapsed time is 0.002907 seconds.
isequal(I1,I2)
ans = logical
1
Recently I needed to parse numbers from text. I automatically tried to use str2double. However, profiling revealed that str2double was the main bottleneck in my code. Than I realized that there is a new note (since R2024a) in the documentation of str2double:
"Calling string and then double is recommended over str2double because it provides greater flexibility and allows vectorization. For additional information, see Alternative Functionality."
WANG Zi-Xiang
WANG Zi-Xiang on 28 Nov 2025 at 0:26
Thanks so much for sharing. I always used sscanf, from a recommandation found here: https://stackoverflow.com/questions/8363132/why-is-str2double-so-slow-in-matlab-as-compared-to-a-mex-function
x = rand(1,50000);
t = string(x);
s1=str2double(t);
s2=double(t);
isequal(s1,s2)
s3 = reshape(sscanf(sprintf('%s#', t), '%g#'), size(t));
isequal(s1,s3)
timeit(@() str2double(t))
timeit(@() double(t))
timeit(@() reshape(sscanf(sprintf('%s#', t), '%g#'), size(t)))
ans =
0.1206
ans =
0.0015
ans =
0.0109
Giordano
Giordano on 22 Aug 2025
Cool! Thanks for sharing!
Mike Croucher
Mike Croucher on 14 Aug 2025
This is interesting @Jan Studnicka, thanks for posting. The double conversion method of string is a relatively new, highly optimised and multithreaded C++ built-in. str2double is a much older .m file and has some um......legacy behaviour! Hence all the notes about not using in the doc.
With that said, the performance gap between the two here is more than I'd like and so I've brought this to the attention of the relvant peple in development to see what can be done.
Nice tip! Thanks for sharing.
Steve Eddins
Steve Eddins on 14 Aug 2025
@Mike Croucher, I'm not seeing a Code Analyzer performance message for str2double. Maybe that could be another enhancement request?
Mike Croucher
Mike Croucher on 15 Aug 2025
This is being discussed internally as we speak. I believe that one of the issues is that the two approaches are not drop-in replacements for each other which makes it tricky to come up with robust automatic advice. All the right people are thinking about this now though thanks to @Jan Studnicka's observation.
Yair Altman
Yair Altman on 18 Aug 2025 (Edited on 18 Aug 2025)
@Mike Croucher as you're looking into possible improvements to str2double, take a look at some of the ideas I've implemented in my drop-in replacement str2number function on the File Exchange (FEX:106265). It provides significant speedup for most common use-cases.
Mike Croucher
Mike Croucher on 19 Aug 2025
Thanks Yair, I have passed that infomation on.
Steve Eddins
Steve Eddins on 14 Aug 2025 (Edited on 14 Aug 2025)
A bit of history -- the original function that people used for this purpose was str2num, which I think dates back to MATLAB 4 around 1990. The function str2num was implemented using eval so that it used exactly the same mechanism that the MATLAB interpreter used to parse MATLAB code. That's how it could handle all the variations in how floating-point, complex constants could be written, as well as the variations in how constant vectors and matrices could be written.
However, the use of eval turned out to be problematic, for both performance and behavior reasons. Calling eval on user-provided input could open a backdoor to potential mischief. Here is what the doc for str2num says about this today: "Security Considerations: str2num is implemented using eval which might lead to undesired side effects. When calling str2num with untrusted user input, use Evaluation='restricted' or str2double to avoid unexpected code execution."
As I recall, eliminating the hidden use of eval was the primary motivation for the introduction of str2double, which I think was around MATLAB 5, 1997. It was faster than str2num and didn't have the potential for bad eval behavior, and MathWorks encouraged people to use it instead.
As @Mike Croucher pointed out, though, str2double supports a lot of "legacy" behavior, as Mike called it. Essentially, str2double was implemented in a way that tries to do nearly the same job as str2num was doing, but without direct access to the parser conversion mechanism. Take a look at str2double.m to get an idea of all the different cases involved just for handling all the ways that complex numbers can be written. Reading it gives me a headache.
I doubt that it is worth the development and testing time (and the risk of introducing incompabilities) to try to optimize all of str2double, but it's possible that there are straightforward ways to optimize certain commonly-used code paths.
Mike Croucher
Mike Croucher on 15 Aug 2025
Thanks so much for the historical perspective Steve. When discussing a language that has been in continuous use for over 40 years, and now has over 5 million users, such perspectives are useful. They help us understand why things are the way they are.
Something that might not make sense in a modern context, made perfect sense 30 years ago and then evolved over time, fixing bugs and satisying user demands. At some point we may have to change lanes and switch to another approach but users (rightly!) expect that all their old code will continue working.
Everyone (including me!) wants the very best that modern tech can allow while never breaking anything old. These are sometimes mutually exclusive requirements. I am somehow reminded of the 'spacebar heating' XKCD comic right now xkcd: Workflow
Steve Eddins
Steve Eddins on 15 Aug 2025
I can think of three core language features, introduced in the late 1990s and early 2000s, whose priority and functional design were influenced by the desire to reduce the need for calling eval. Oooh, I can feel a new blog post coming.
Sorry for drifting completely off topic. 🙂
goc3
goc3 on 15 Aug 2025
That is a funny comic.
I think that MathWorks has struck a good balance in this respect. As I understand it, most of the time older functions, rather than being fully deprecated, are given the "not recommended" status in documentation and Editor suggestions, with a brief description of a newer function to use instead. This way, MathWorks can stop developing dead-end functions (that many users may still rely upon) while focusing on the newer ones.
Of course, the suggested newer function may not be a one-for-one replacement, and sometimes I find that I do have to stick with the older function. But, it is very helpful to know that (1) current functionality should work for the foreseeable future and (2) there is an improved option available.
Image Analyst
Image Analyst on 14 Aug 2025
tic and toc is certainly easier to remember than the syntax for using timeit. If I were to use timeit, I'd probably have to look up the documentation every time.
Rik
Rik on 15 Aug 2025
Really? I don't believe I've even opened the documentation once in the past 10 years. I just assume it needs an anonymous function (or handle) that can run without any further input.
So I must admit that it isn't as easy on the eyes as tic-toc, but is this really so much more convoluted than I think? I'm not trying to put you down, just genuinely curious.
goc3
goc3 on 15 Aug 2025
My biggest hesitation with using timeit is that it requires a function handle as input. Often, what I am timing is ad hoc and does not align clearly with function or class boundaries.
I also fully understand the (typically longer) startup time for the first run and potential lack of precision when the runtime is small. So, I always make sure to run the tic/toc cycle at least once before recording the time and run it many times in a loop (if necessary) to generate an overall execution time that is on the order of at least 1–10 seconds from which to calculate the average runtime.
Steve Eddins
Steve Eddins on 15 Aug 2025
That is a well-motivated and sound approach.
Steve Eddins
Steve Eddins on 15 Aug 2025
Another factor to be aware of is that MATLAB can often execute code in functions faster than it can execute the same code entered interactively in the command window.
Rik
Rik on 14 Aug 2025
In this case the difference is pretty small, but you shouldn't use tic toc for comparing functions. timeit considers things like the slower first use of a function and statistical variation.
x = rand(1,50000);
t = string(x);
s1=str2double(t);
s2=double(t);
isequal(s1,s2)
ans = logical
1
timeit(@() str2double(t))
ans = 0.2194
timeit(@() double(t))
ans = 0.0018
Jan Studnicka
Jan Studnicka on 14 Aug 2025 (Edited on 14 Aug 2025)
Thanks for the comment Rik. I usually prefer running tic/toc several times over the timeit from the same reasons @Mike Croucher mentioned in his blog post Should we ban tic/toc? However, in this case, timeit would be better, because the reader can see only one run.
Steve Eddins
Steve Eddins on 14 Aug 2025
I encourage anyone interested in tic/toc vs. timeit to check out my 15-Jan-2025 blog post, "The Story of TIMEIT." It describes the original motivations for creating it, how it works, its move into MATLAB, and some discussion about why people may prefer one or the other solution. There is also some speculative discussion about possible enhancements to timeit.
xingxingcui
xingxingcui on 14 Aug 2025
interesting...