You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Is there a way to extract parts of a multi digit number in MatLab?
88 views (last 30 days)
Show older comments
Title says it all. I'm wondering if there is a way to extract parts of a multi digit number in MatLab?
For example: user enter 1298 I want to take out the first two digits (12) set it equal to some variable, and the last two digits (98) and set that to some variable. I was thinking there might be some way to do this using strings, but I was wondering what you guys thought.
Answers (3)
Walter Roberson
on 7 Mar 2012
Edited: Stephen23
on 27 Feb 2017
s = num2str(1298);
s12 = str2double(s(1:2));
s34 = str2double(s(3:4));
5 Comments
a n
on 9 Oct 2017
How come num2str drops out values like 1298.00, the .00 being the values I am referencing? I note that setting format as long or short has no effect on it either.
Walter Roberson
on 9 Oct 2017
Edited: Walter Roberson
on 9 Oct 2017
"a n", I was not able to reproduce that on R2017b .
I find that with the default format, num2str() first converts numbers with absolute value less than 1 to have 5 significant figures after the decimal place, and numbers with absolute value greater than 1 to have 4 significant figures after the decimal place. Then, having done that, it removes all trailing '0' after the decimal place on the result, and if the result of that has no remaining decimal places, it removes the '.' as well.
Brendan Görres
on 29 Nov 2021
What would I have to do if I don't have a single scalar but a vector? So that I extract of every number in each row digit 1 and 2 to a variable and 3 and 4 to another.
Image Analyst
on 29 Nov 2021
@Brendan Görres, perhaps you didn't look over all the answers (like mine). Just apply it to your vector:
a = [1298; 3467; 5010]; % Vector with different numbers in each row.
first2 = floor(a/100)
first2 = 3×1
12
34
50
second2 = rem(a, 100)
second2 = 3×1
98
67
10
Image Analyst
on 8 Mar 2012
Not sure why you're interested in using strings, but if that's not a requirement you can do this:
a=1298
first2 = floor(a/100)
second2 = rem(a, 100)
29 Comments
Anna2017
on 27 Feb 2017
Hi Image Analyst, May I know why it does not work for big numbers? I would just like to take the first 10 digits as one value and the remaining as another value.
First 10 digits work fine but when there are zeros before or after 11 digit onwards, MATLAB gives a wrong result. For example, the following 2 values :
- 1475053846358600000: First 10 digit should be 1475053846 and remaining digits should be 358600000. In MATLAB first 10 digits are identified correctly 1475053846 but the remaining becomes wrong value. It shows as 358599936.
- 1475053847002150000 : First 10 digit should be 1475053847 and remaining digits should be 002150000. In MATLAB first 10 digits are identified correctly 1475053847 but the remaining becomes wrong value again. It becomes as 2149888.
The code I have typed is:
numvalue = 1475053847002150000;
first10 = floor(numvalue/1000000000);
second2 = rem(numvalue, 1000000000);
I have also tried other methods such as num2str etc. but still after 10 digits, values are not quite correct. I would like to retain the zero values before and after please. Kindly let me know if you have any idea on this. Thank you in advance.
Stephen23
on 27 Feb 2017
Edited: Stephen23
on 27 Feb 2017
@banani patra: You are getting those values because you are exceeding the precision limit of double floating point numbers:
double can store 15-17 decimal digits of precision. You are trying to access 19 digits of precision, digits which the double class simply does not contain. Therefore you will get rubbish as an output.
As an alternative you could:
- Work exclusively with strings.
- Use syms, or the VPA toolbox.
- Try John D'Errico's brilliant VPI FEX submission:
Walter Roberson
on 27 Feb 2017
If you can create the numbers as uint64 then you can use the above techniques.
numvalue = uint64(1475053846358600000);
first10 = floor(numvalue/1000000000);
second2 = rem(numvalue, 1000000000);
and if you happen to have a string then do not use %e or %f or %g to parse it:
S = '1475053846358600000'
>> fprintf('%u\n', sscanf(S,'%e'))
1475053846358599936
>> fprintf('%u\n', sscanf(S,'%f'))
1475053846358599936
>> fprintf('%u\n', sscanf(S,'%g'))
1475053846358599936
>> fprintf('%u\n', sscanf(S,'%u'))
4294967295
>> fprintf('%u\n', str2double(S))
1475053846358599936
>> fprintf('%u\n', sscanf(S,'%lu'))
1475053846358600000
so use %lu with sscanf to convert the number if it is in a string.
Stephen23
on 27 Feb 2017
Although keep in mind that even uint64 has a maximum of 20 digits, so you will exceed its limit quite easily.
Anna2017
on 27 Feb 2017
Thank you Stephen and Walter for the explanation.
However, when I try for example:
numvalue = uint64(1475054010091340000);
first10 = floor(numvalue/1000000000);
second2 = rem(numvalue, 1000000000);
Result is first10: 1475054010 (Correct)
Result of second2: 91340000 (Instead of 091340000).
Any idea how to correct this second2 value. The front zeros are important to me as it affects the precision for the final answer. I do not mind using strings as long as the end result serves the purpose. Thank you.
Walter Roberson
on 27 Feb 2017
As strings, then:
numvalue = uint64(1475054010091340000);
temp = sprintf('%lu', numvalue);
first10 = temp(1:10);
second2 = temp(11:end);
"The front zeros are important to me as it affects the precision for the final answer."
Then you are doing your calculation incorrectly. Every number is preceded by an indefinite number of 0. You cannot justify that your split should not instead be 0000147505 4010091340000 because for 1475054010091340000 there is an equally valid claim that that number is "really" 00001475054010091340000
Stephen23
on 27 Feb 2017
"Every number is preceded by an indefinite number of 0"
and possibly trailing as well. Pity us poor humans who cannot comprehend the infinite digits and dimensions that every number really has.
Anna2017
on 28 Feb 2017
Thank you very much. It works now. Appreciate your help.
But I have one last doubt. Lets say I have a value of '30.091340000' as I combined two strings to form this. How may I convert this to number without affecting the values?
When I simply do a str2num('30.091340000'), the answer becomes 30.0913. How can I get 30.091340000 as a number? I need it to be number to put it into a table.
Thank you again in advance.
Walter Roberson
on 28 Feb 2017
Format controls are not available for table() objects. To get a certain number of digits, you would have to convert the items to strings.
Image Analyst
on 28 Feb 2017
Of course it was already a string to begin with, so you can just use the original string. By the way, format long g crops off any trailing zeros on the right so you won't get 4 zeros on the right with any numeric format - you gotta stick with strings.
Anna2017
on 28 Feb 2017
Thank you format long g works for my previous question but I have another further question.
Something wrong again at the beginning. I am trying to read a excel file which is full of these numbers. After that I will do the first10 and second2 value.
However, when I read from the excel file(either through readtable or xlsread command), it already shows a wrong value. Even if I try to read it as uint64. For example:
t = readtable('Time.xlsx'); %this just has one column of all the time values
timeepoch = uint64(t.time); % Extract the "time" column.
timeepoch1 = t.time; % Extract the "time" column.
Once the above is executed, timeepoch value is in uint64 format and timeepoch1 is in double. But when I double click on the values:
Originally my value is 1475053846314510000 in the excel file.
But in timeepoch it becomes 1475053846314510080 (80 wrongly added at the end)
and timeepoch1 result is 1.475053846314510e+18.
Next, when I do the above advised steps,
numvalue = uint64(timeepoch1);
temp = sprintf('%lu', numvalue);
first10 = temp(1:10);
second2 = temp(11:end);
Answer is wrong again showing first10 = 1475053846 and second2 = 314510080. Second2 value is wrong.
Any idea what am I doing wrong? As long as I can avoid the wrong info at the end eg. '80' in this case, it is good. I do not mind if the second2 answer is just 31451 or 314510000 (preferred) as long as there are no wrong values.
Please advise. Thank you.
Walter Roberson
on 28 Feb 2017
You will have to use the Format option of readtable() as it defaults to expecting floating point.
Anna2017
on 28 Feb 2017
Do you have an example?
When I simply do
t = readtable('Time.xlsx','Format', '%uint64');
It shows an error message of 'Invalid parameter name: Format.'
I am using Matlab R2014b, not sure if the format option is supported.
Walter Roberson
on 28 Feb 2017
See the example of Create and Format table at
https://www.mathworks.com/help/matlab/ref/readtable.html
Your version might be too old to support it. If so then you will need to find an alternative way to read the file. If you are using csv or text file then textscan. If you are using xls files then unless you have applied custom format of cells then trailing 0 decimals are not stored in the file. If you are using xlsx files then whether the source bothered to write trailing 0 decimals into the file depends on how the file was created. xlswrite to xlsx for example does not preserve trailing 0 decimals, not even for fields you indicated were strings instead of numeric!
Anna2017
on 28 Feb 2017
I looked through the 'readtable' matlab page you have sent before asking for an example as I could not find any examples on that page and I am not sure if Format works on my MATLAB version.
I can read either xlsx or csv file (now trying with xlsx), both of them have values such as 1475053846314510000. so my original files has no problem. Just that when I read them to MATLAB there is problem.
I did not get your reply about textscan? My values are numbers so I do not think it is applicable? Any advise is appreciated.
Walter Roberson
on 28 Feb 2017
The use of format is the third example in the R2016b document for readtable. However your version might be too old for that feature.
xls files are binary files in a binary format that is not really documented (but has been reverse engineered).
xlsx files are really zip files of directories that contain text files. Once unzipped they can be processed as text files. However because they are structured text sort of like html you would probably use tools like regexp to pull them apart instead of textscan.
csv files are text files, and textscan is a useful tool for scanning text files to convert the text into numbers.
Anna2017
on 1 Mar 2017
Thank you for the reply. Had been trying to troubleshoot reading the file but still getting error. I managed to get MATLAB 2016a installed however, the 'format' parameter does not work for the xlsx file I have. As my original data is in a csv file, I would just like to read the first column from there and do as the above.. numvalue = uint64(value extracted from the file). and so on..
Is there a good way to extract just first column of the csv file (with uint64 formatting from the beginning to restore all the values) as the csv file i have is huge and I only need the first column. I had been trying csvread, xlsread,fopen, textscan etc but still no expected result yet. Thank you.
Anna2017
on 1 Mar 2017
Even though I am reading from the original csv file:
filename = 'final.csv';
timeepoch = xlsread(filename, 'A:A' );
lengthofvalue=length(timeepoch);
for i = 1: lengthofvalue
numvalue = timeepoch(i);
temp = sprintf('%lu', numvalue);
first10 = temp(1:10);
second2 = temp(11:end);
end
Results: first10 = 1475053846
second2 = 314510080
Result for second2 is still wrong ('80' at the end). Have any idea how do I correct this? Still stuck at the same query.
Walter Roberson
on 1 Mar 2017
fid = fopen('final.csv','rt');
data=textscan(fid, '%lu%*s', 'whitespace', '\n') ;
fclose(fid)
data{1}
I would need recheck the whitespace parameter
Anna2017
on 2 Mar 2017
Unfortunately have following error for the above commands.
===========
Unable to parse the format string at position 1 ==> %lu%*s Unsupported format specifier '%l'. See the documentation for TEXTSCAN for supported formats.
Error in fileopentest (line 19) data=textscan(fid, '%lu%*s', 'whitespace', '\n') ;
======================
My csv file has many columns, I would just like to extract the first column. It has a title of %time as shown in the attached image. Kindly advise. Thank you.
Anna2017
on 2 Mar 2017
Sorry, I cannot attach my csv file as it is confidential. I have sent a screenshot of it here in my last message. I am just trying to get the first column out of it.
Walter Roberson
on 2 Mar 2017
fid = fopen('Time.csv', 'rt');
data_cell = textscan(fid, '%10f%f%*[^\n]', 'headerlines', 1, 'delimiter', ',');
fclose(fid);
first10 = data_cell{1};
second2 = data_cell{2};
This will create two column vectors of double, with the first one being 10 digit numbers (unless a row happens to start with 0).
At this time you might perhaps want
eventtime = datetime(first10,'convertfrom','posixtime') + seconds(second2/10^9);
(which should work in R2014b and later)
Caution: posix times before approximately 09-Sep-2001 01:46:40 have fewer leading decimals, but you have specified "first 10" digits, so if you are dealing with posix times you might wish to reconsider the specification.
Anna2017
on 2 Mar 2017
Hi Walter, Really appreciate your advise. But I am sorry I am still having wrong output for second2. It generates 2 column vectors as you have mentioned but second2 values for last few digits are not correct again.
For example, the first value at my csv file: 1475053846314510000
First10, first value is 1475053846 (Correct)
Second2, first value is 314515832 (It should be 314510000 or 31451)
Another example, For leading zeroes too it does not work well. Eg. for value of 1475053847002150000
First10 is 1475053847 Second2 is 2154182 (I need it to be 00215 or 00215000)
Thank you for sharing about posixtime but after the separation of first 10 and second2 is done, I am able to convert from unix epoch time (original data) to normal time without any error. Just at the beginning about reading from csv and separating to first10 and second2 I am having error hence stuck here. Thank you so much so far..
Anna2017
on 2 Mar 2017
I also tried using textscan(fid, '%10u64%u64%*[^\n]', 'headerlines', 1, 'delimiter', ','); But it gives the same wrong output for second2 as above.
Walter Roberson
on 2 Mar 2017
On your system, please try this experiment:
S = '1475053846314510000'
format long g
textscan(S, '%10f%f')
and tell me what the results are.
Anna2017
on 2 Mar 2017
Hi Walter, This works good in the command window, that is why previously I had said it works. its just when I import in the values from the original file somehow from beginning the value gets converted to wrong value: To answer your question, the results are as the following:
S = 1475053846314510000
ans =
[1475053846] [314510000]
Walter Roberson
on 2 Mar 2017
Not much more I can do without a sample .csv file of at least one line that gives the wrong result for you.
zahid Hasan
on 22 Jan 2017
Edited: Walter Roberson
on 22 Jan 2017
k=double(num2str(1298))-double('0');
% k becomes k=[1 2 9 8]
2 Comments
Image Analyst
on 22 Jan 2017
He wanted
k1 = 12
k2 = 98
However it's still not clear if he's starting with a number (as my answer assumes), or a string (as Walter's answer assumes). Since it is now 5 years later, I doubt we'll ever get an answer.
See Also
Categories
Find more on Data Type Conversion in Help Center and File Exchange
Tags
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)