This question already has answers here:
What is the Small "e" in Scientific Notation / Double in Matlab
(2 answers)
Closed 7 years ago.
How can I write a number/Integer value to power of 10, e.g. 1000 as 10^3? I am writing code whose output is a string of very large numbers. My output in longEng format is:
4.40710646596169e+018
16.9749211806197e+186
142.220634811050e+078
508.723835280617e+204
1.15401317731033e-177
129.994388899690e+168
14.3008811642810e+153
1.25899227268954e+165
24.1450064703939e+150
627.108997290435e+144
2.03728822649372e+177
339.903986115177e-066
150.360900017430e+183
5.39003779219462e+135
183.893417489826e+198
648.544709490386e+045
19.7574461055182e+198
3.91455750674308e+102
6.41548629454028e-114
70.4943280639616e+096
19.7574461055182e+198
3.11450571506133e-009
249.857950606210e+093
4.64921904682151e+180
750.343029004712e+147
I want these results to be in a format of power of 10, so that I can easily do arithmetic operations for my next function.
you can write format shortE and see you output like this:
4.4071e+18
1.6975e+187
1.4222e+80
5.0872e+206
If you only want to print the data in scientific format, the Matlab itself can do this for you.
If you can to obtain the scientific notation form as
a * 10^b,
i.e., obtain the coefficient a and the exponent b, you can first obtain the b as:
b = floor(log10(abs(x)));
then the a as:
a = x * 10^(-b);
from my understanding you wish to take your number e.g. 4.40710646596169e+018 and split it up into:
4.40710646596169 and 018 once you have them separated you you can perform operations as you wish.
You can even join them back to look like: 4.40710646596169^018 if you so desire (although to look like that they would be strings and therefore mathematical operations on the number would be NAN).
Since e represents to the power 10 and is present in all numbers you listed this is a simple process with many solutions, here is one.
% format long is very important otherwise it will appear to you that you have
%lost precision. MATLAB hides precision from view to save screen space and to
%produce less confusing results to the viewer. (the precision is still there but
%with format long you will be able to see it.
format long
x = 4.40710646596169e+018;
%convert your number into a string, this will allow you to split the number based
%on the always present e+ 'delimiter' (not really a delimiter but looks like one')
s = num2str(x);
%use strsplit to perform the split in the required place. it will output a 1x2
%cell
D = strsplit(s, {'e+'});
%extract each cell to a separate variable. in fact D{1} can be directly used for
%the input of the next function.
D11 = D{1};
D22 = D{2};
%convert the separated strings back into numbers with double precision (keep
%maintin value accuracy)
D1 = str2double(D11)
D2 = str2double(D22)
in order to do this operation on an entire column vector it is simply a matter of using a for loop to iterate through all the numbers you have.
Related
I have a set of integer values, for example:
V = [26767559, 6022443, 9923637]; % etc.
For my application, it is convenient to represent them as <rounded_mantissa>E5 (that is, some_val*105), so for the above examples I want to get:
N = ["268E5", "60E5", "99E5"]; % I won't mind if it's E+05
At the moment, I'm using one of several conceivable workarounds to achieve this output,
N = round(V*1E-5) + "E5";
but I'd like to know if it's possible to specify the formatSpec of sprintf, num2str (etc.) such that it would output numbers with a specific value for the exponent (in this case, 5), without performing division (like in num2str(round(V/1E5).','%3uE5')).
I'm using R2018a.
You can at least remove the use of round, then I don't think there's any further short-hand because it's just a single division...
N = num2str( V/1e5, '%.0fE5' )
The .0 precision operator will force the 0 decimal place rounding for you anyway.
You can only specify the number of digits (significant or after the decimal point) using the formatSpec property, so unless you've got fixed numbers of digits (which you don't) you won't be able to use that alone.
Let's say I create some number A, of the order 10^4:
A = 81472.368639;
disp(A)
8.1472e+04
That wasn't what I wanted. Where are my decimals? There should be six decimals more. Checking the variable editor shows me this:
Again, I lost my decimals. How do I keep these for further calculations?
Scientific notation, or why you didn't lose any decimals
You didn't lose any decimals, this is just MATLAB's way of displaying large numbers. MATLAB rounds the display of numbers, both in the command window and in the variable editor, to one digit before the dot and four after that, using scientific notation. Scientific notation is the Xe+y notation, where X is some number, and y an integer. This means X times 10 to the power of y, which can be visualised as "shift the dot to the right for y places" (or to the left if y is negative).
Force MATLAB to show you all your decimals
Now that we know what MATLAB does, can we force it to show us our number? Of course, there're several options for that, the easiest is setting a longer format. The most used for displaying long numbers are format long and format longG, whose difference is apparent when we use them:
format long
A
A =
8.1472368639e+04
format longG
A
A =
81472.368639
format long displays all decimals (up to 16 total) using scientific notation, format longG tries to display numbers without scientific notation but with most available decimals, again: as many as there are or up to 16 digits, both before and after the dot, in total.
A more fancy solution is using disp(sprintf()) or fprintf if you want an exact number of decimals before the dot, after the dot, or both:
fprintf('A = %5.3f\n',A) % \n is just to force a line break
A = 81472.369
disp(sprintf('A = %5.2f\n',A))
A = 81472.37
Finally, remember the variable editor? How do we get that to show our variable completely? Simple: click on the cell containing the number:
So, in short: we didn't lose any decimals along the way, MATLAB still stores them internally, it just displays less decimals by default.
Other uses of format
format has another nice property in that you can set format compact, which gets rid of all the additional empty lines which MATLAB normally adds in the command window:
format compact
format long
A
A =
8.147236863931789e+04
format longG
A
A =
81472.3686393179
which in my opinion is very handy when you don't want to make your command window very big, but don't want to scroll a lot either.
format shortG and format longG are useful when your array has very different numbers in them:
b = 10.^(-3:3);
A.*b
ans =
1.0e+07 *
0.0000 0.0001 0.0008 0.0081 0.0815 0.8147 8.1472
format longG
A.*b
ans =
Columns 1 through 3
81.472368639 814.72368639 8147.2368639
Columns 4 through 6
81472.368639 814723.68639 8147236.8639
Column 7
81472368.639
format shortG
A.*b
ans =
81.472 814.72 8147.2 81472 8.1472e+05 8.1472e+06 8.1472e+07
i.e. they work like long and short on single numbers, but chooses the most convenient display format for each of the numbers.
There's a few more exotic options, like shortE, shortEng, hex etc, but those you can find well documented in The MathWork's own documentation on format.
I have a 12-bit binary that I need to convert to a decimal. For example:
A = [0,1,1,0,0,0,0,0,1,1,0,0];
Bit 1 is the most significant bit, Bit 12 is the least significant bit.
Note: This answer applies primarily to unsigned data types. For converting to signed types, a few extra steps are necessary, discussed here.
The bin2dec function is one option, but requires you to change the vector to a string first. bin2dec can also be slow compared to computing the number yourself. Here's a solution that's about 75 times faster:
>> A = [0,1,1,0,0,0,0,0,1,1,0,0];
>> B = sum(A.*2.^(numel(A)-1:-1:0))
B =
1548
To explain, A is multiplied element-wise by a vector of powers of 2, with the exponents ranging from numel(A)-1 down to 0. The resulting vector is then summed to give the integer represented by the binary pattern of zeroes and ones, with the first element in the array being considered the most significant bit. If you want the first element to be considered the least significant bit, you can do the following:
>> B = sum(A.*2.^(0:numel(A)-1))
B =
774
Update: You may be able to squeeze even a little more speed out of MATLAB by using find to get the indices of the ones (avoiding the element-wise multiplication and potentially reducing the number of exponent calculations needed) and using the pow2 function instead of 2.^...:
B = sum(pow2(find(flip(A))-1)); % Most significant bit first
B = sum(pow2(find(A)-1)); % Least significant bit first
Extending the solution to matrices...
If you have a lot of binary vectors you want to convert to integers, the above solution can easily be modified to convert all the values with one matrix operation. Suppose A is an N-by-12 matrix, with one binary vector per row. The following will convert them all to an N-by-1 vector of integer values:
B = A*(2.^(size(A, 2)-1:-1:0)).'; % Most significant bit first
B = A*(2.^(0:size(A, 2)-1)).'; % Least significant bit first
Also note that all of the above solutions automatically determine the number of bits in your vector by looking at the number of columns in A.
Dominic's answer assumes you have access to the Data Acquisition toolbox. If not use bin2dec:
A = [0,1,1,0,0,0,0,0,1,1,0,0];
bin2dec( sprintf('%d',A) )
or (in reverse)
A = [0,1,1,0,0,0,0,0,1,1,0,0];
bin2dec( sprintf('%d',A(end:-1:1)) )
depending on what you intend to be bit 1 and 12!
If the MSB is right-most (I'm not sure what you mean by Bit 1, sorry if that seems stupid):
Try:
binvec2dec(A)
Output should be:
ans =
774
If the MSB is left-most, use fliplr(A) first.
I am trying to build a finantial application that handle economical data using Matlab. The file I want to load is in a csv file and are double numbers in this format '1222.3'. So far, I am just working with one dimension and I am able to load the data into a vector.
The problem is that the data is loaded into the vector in String format. To change all the vector into double format I use str2double(vector), but the numbers into the vector end like this:
1222.3 -> 1.222
153.4 -> 0.1534
I have tried to multiply the vector per 100 (vector.*100), but did not work.
Any idea?
If your vector components are sufficiently large enough, MATLAB will print the numbers in exponential format.
>> a = 1234.56
a =
1.2346e+03
The numbers are also shown in scientific notation in the workspace browser:
You can print the numbers in decimal form using e.g. fprintf:
>> fprintf('%5.3f\n',a)
1234.560
>>
As a side note, 1.222 * 100 ≠ 1222 ...
Matlab automatically pulls some common factor out numerical vectors, which has confused me many times myself. The line that gives the common factor is easy to miss, especially for large vectors, because it is displayed at the top.
If I define a vector with the two number you gave, Matlab displays it to me in the following way:
It pulled out a factor of 1000, as indicated by the line 1.0e+03 *.
I have a 12-bit binary that I need to convert to a decimal. For example:
A = [0,1,1,0,0,0,0,0,1,1,0,0];
Bit 1 is the most significant bit, Bit 12 is the least significant bit.
Note: This answer applies primarily to unsigned data types. For converting to signed types, a few extra steps are necessary, discussed here.
The bin2dec function is one option, but requires you to change the vector to a string first. bin2dec can also be slow compared to computing the number yourself. Here's a solution that's about 75 times faster:
>> A = [0,1,1,0,0,0,0,0,1,1,0,0];
>> B = sum(A.*2.^(numel(A)-1:-1:0))
B =
1548
To explain, A is multiplied element-wise by a vector of powers of 2, with the exponents ranging from numel(A)-1 down to 0. The resulting vector is then summed to give the integer represented by the binary pattern of zeroes and ones, with the first element in the array being considered the most significant bit. If you want the first element to be considered the least significant bit, you can do the following:
>> B = sum(A.*2.^(0:numel(A)-1))
B =
774
Update: You may be able to squeeze even a little more speed out of MATLAB by using find to get the indices of the ones (avoiding the element-wise multiplication and potentially reducing the number of exponent calculations needed) and using the pow2 function instead of 2.^...:
B = sum(pow2(find(flip(A))-1)); % Most significant bit first
B = sum(pow2(find(A)-1)); % Least significant bit first
Extending the solution to matrices...
If you have a lot of binary vectors you want to convert to integers, the above solution can easily be modified to convert all the values with one matrix operation. Suppose A is an N-by-12 matrix, with one binary vector per row. The following will convert them all to an N-by-1 vector of integer values:
B = A*(2.^(size(A, 2)-1:-1:0)).'; % Most significant bit first
B = A*(2.^(0:size(A, 2)-1)).'; % Least significant bit first
Also note that all of the above solutions automatically determine the number of bits in your vector by looking at the number of columns in A.
Dominic's answer assumes you have access to the Data Acquisition toolbox. If not use bin2dec:
A = [0,1,1,0,0,0,0,0,1,1,0,0];
bin2dec( sprintf('%d',A) )
or (in reverse)
A = [0,1,1,0,0,0,0,0,1,1,0,0];
bin2dec( sprintf('%d',A(end:-1:1)) )
depending on what you intend to be bit 1 and 12!
If the MSB is right-most (I'm not sure what you mean by Bit 1, sorry if that seems stupid):
Try:
binvec2dec(A)
Output should be:
ans =
774
If the MSB is left-most, use fliplr(A) first.