I have a vector of doubles and I want to see what are the exact numbers inside the vector I get in format long.
1.0e+03 *
-0.002202883146567
1.182072110137121
-0.002242966651629
-0.000584787748712
0.022251505213305
0.037460846794487
Can I make some adjusment so that I can directly see the number, rounded to let's say the 5th or 6th element after the decimal point, whenever I type the name of the variable?
fprintf('%.6f\n', 0.037460846794487)
It'll round 0.037460846794487 to 6 decimal places as shown:
>> fprintf('%.6f\n', 0.037460846794487)
0.037461
Or you can also use sprintf('%.6f\n', 0.037460846794487) , particularly, if you want to save the rounded off output in a variable.
>> a=sprintf('%.6f\n', 0.037460846794487)
a =
0.037461
and for the matrix you mentioned, you can make the following adjustment:
%Your matrix
A = 1.0e+03 * [ -0.002202883146567 ;
1.182072110137121 ;
-0.002242966651629 ;
-0.000584787748712 ;
0.022251505213305 ;
0.037460846794487 ];
A = sprintf('%.6f\n', A) %Adjusted to 6 decimal digits
Related
Is there a way to convert a decimal number between $0$ and $1$ that is not integer to base 4 in Matlab? E.g. if I put 2/5 I want to get 0.12121212... (with some approximation I guess)
The function dec2base only works for integers.
Listed in this post is a vectorized approach that works through all possible combinations of digits to select the best one for the final output as a string. Please note that because of its very nature of creating all possible combinations, it would be memory intensive and slower than a recursive approach, but I guess it could be used just for fun or educational purposes!
Here's the function implementation -
function s = dec2base_float(d,b,nde)
%DEC2BASE_FLOAT Convert floating point numbers to base B string.
% DEC2BASE_FLOAT(D,B) returns the representation of D as a string in
% base B. D must be a floating point array between 0 and 1.
%
% DEC2BASE_FLOAT(D,B,N) produces a representation with at least N decimal digits.
%
% Examples
% dec2base_float(2/5,4,4) returns '0.1212'
% dec2base_float(2/5,3,6) returns '0.101211'
%// Get "base power-ed scaled" digits
scale = b.^(-1:-1:-nde);
%// Calculate all possible combinations
P = dec2base(0:b^nde-1,b,nde)-'0';
%// Get the best possible combination ID. Index into P with it and thus get
%// based converted number with it
[~,idx] = min(abs(P*scale(:) - d));
s = ['0.',num2str(P(idx,:),'%0.f')];
return;
Sample runs -
>> dec2base_float(2/5,4,4)
ans =
0.1212
>> dec2base_float(2/5,4,6)
ans =
0.121212
>> dec2base_float(2/5,3,6)
ans =
0.101211
Example: 6.321: I need it to be 6.322.
5.14875: I need it to be 5.14876.
How can I do this?
If you represent numbers as floating point or double precision floating point, this problem is a disaster.
If you can read in a number as a string (you mentioned get the number with the input command), you could do:
x = input('ENTER A NUMBER: ','s');
decimal_place = find(fliplr(x)=='.',1) - 1;
x_val = str2double(x);
if(~isempty(decimal_place))
y = x_val + 10 ^ -decimal_place;
else % if there is no decimal place, find first non-zero digit to get sigfig
warning('ambiguous number of significant digits');
first_nonzero_digit = find(fliplr(x)~='0',1);
if(~isempty(first_nonzero_digit))
y = x_val + 10 ^ (first_nonzero_digit - 1);
else
y = x_val + 1;
end
end
disp('your new number is');
disp(y);
Example test runs:
ENTER A NUMBER: 1.9
your new number is
2
ENTER A NUMBER: 3510
your new number is
3520
ENTER A NUMBER: 323.4374
your number is
323.4375
ENTER A NUMBER: 0
your number is
1
#AndrasDeak - I think you're right the first time. The hard part is not the rounding - it's defining the "last" decimal.
Since floating point numbers aren't exact, I can't think of a reliable way to find that "last" decimal place - in any language.
There is a very hacky way that comes to mind, though. You could "print" the number to a string, with 31 numbers after the decimal point, then working right from the dot, find the first place with 15 0s. (Since double precision numbers can only stably represent the first 14 decimal places and you get a 15th that varies, 31 decimal place will ALWAYS give you at least 15 0s after the last sig digit.)
>> a = 1.34568700030041234556
a =
1.3457
>> str = sprintf('%1.31', a)
str =
Empty string: 1-by-0
>> str = sprintf('%1.31f', a)
str =
1.3456870003004124000000000000000
>> idx = strfind(str, '000000000000000')
idx =
19
>> b = a*10^(idx(1)-3)
b =
1.3457e+16
>> sprintf('%10.20f', b)
ans =
13456870003004124.00000000000000000000
>> c = b+1
c =
1.3457e+16
>> sprintf('%10.20f', c)
ans =
13456870003004124.00000000000000000000
>> final = floor(c)/10^(idx(1)-3)
final =
1.3457
>> sprintf('%10.31f', final)
ans =
1.3456870003004124000000000000000
I think that's a relatively reliable implementation.
http://www.mathworks.com/matlabcentral/answers/142819-how-to-find-number-of-significant-figures-in-a-decimal-number
assuming your just trying to do regular rounding:
i'd use the round function built into matlab.
let's do your example above..
5.14875 has 5 decimal places and you want it to be converterd to 5.14876.
Lets assume you that the 6th decimal place was 9 (so your number is 5.148759)
%Step 1:changethe format so that your going to be able to see all of the
%decimal places
format long
%step2:now enter the original number
OriginalNumber=5.148755
%step 3 take the original number and round it to your new number
NewNumber=round(OriginalNumber,5)
this solution will not work if the 6th number (that you did not show) was a <5 because the computer will not know to round up
assuming your just trying to cut the numbers off...
You cannot do this in regular default matlab floating point numbers. To keep my explination simple I'll just state that without an explination. I'd do some review on the different ways matlab stores # (int vs floating point) on the matlab website. They have excellent documentation.
I am writing a mesh smoother in Matlab for a particular CFD code. The requirements for the mesh data file are very strict, and so the number format must be very specific. The definition for one quadrilateral element is as follows (Where the 2nd row is the x coordinates and 3rd row is y coordinates).
ELEMENT 14 [ 1Q] GROUP 0
5.000000 10.00000 10.00000 5.000000
2.000000 2.000000 4.500000 4.500000
As you can see, each number takes up exactly 8 characters. Once the whole mesh has been passed through my smoother, I need to write the numbers back to a file. the closest I've gotten to this number format is with the following operator:
%#7.7g
I don't think I can use %f, as this specifies the number of digits after the decimal, which in my case varies (I have coordinates that go from less than one to over 100). the only issue that this operator is giving me is when I have numbers less than one, it only retains 7 sig figs, and the number ends up being 9 characters long; for example:
0.9313373
Does anyone know the correct operator, or have a workaround? Much appreciated.
Single format spec:
If you can live with only 4 digit precision (decimal part after the .) out of your 8 characters, and if the mesh reading program can handle padding 0 (i.e. if it can read values like 007.2365 properly), then the simplest and quickest option is to use only the format specifier.
For example, let's define an input a with different order of magnitude:
a=[ 1 234 7 ;
12 2 0.123456789 ;...
5 2.36 0.0024 ] ;
Your highest number is 234, so that leaves 4 digits for the fractional part. If you accept that precision for all the numbers in your Matrix, then you're all set with a simple instruction:
fmt='%08.4f %08.4f %08.4f\n'; %// hard coded format specifier
sprintf(fmt,a.') %'// we transpose a to keep the same shape in the output since sprintf is column major.
ans =
001.0000 234.0000 007.0000
012.0000 002.0000 000.1235
005.0000 002.3600 000.0024
If you don't know in advance what will be the maximum order of magnitude of your data you can set the format specifier programmatically:
nDigitTotal = 8 ;
nmax = ceil( log10(max(a(:))) ) ; %// max order of magnitude of numbers in "a"
f = sprintf('%%0%d.%df',nDigitTotal,nDigitTotal-nmax-1) ; %// format spec for 1 number
fmt = [f '\t' f '\t' f '\n'] ; %// format spec for a line of 3 numbers
s = sprintf(fmt,a.')
Will give the same result as above. Add a check to make sure there are no extreme values in your matrix which will eat your precision.
Individual format spec:
Lastly, if that precision and/or the leading zero do not work for you, you can resort to a more elaborate solution. I quite like the idea from excaza of setting a mask to specify the precision for each number. I'll produce my own version, very slightly different, which account for numbers at any precision and allow array output. However, if you end up using this solution give credit to excaza since he was the inspiration for this evolution:
a = a.' ; %'// transpose from beginning/ thats done
nDigitTotal = 8; %// Total number of characters
mask = nDigitTotal(ones(size(a))) ; %// Create mask
nOrder = floor( log10(a) ) ; %// find order of magnitude of each element in the matrix
mask = mask - nOrder.*(nOrder>0) -1 ; %// adjust mask according to "nOrder" (only for nOrder>0)
temp = [mask(:)';a(:)']; %// Stack the vectors and weave them
f = '%7.*f' ; %// basic format spec
fmt = [f '\t' f '\t' f '\n'] ; %// build your line
sprintf(fmt,temp) %// go for it
will give you:
ans =
1.0000000 234.00000 7.0000000
12.000000 2.0000000 0.1234568
5.0000000 2.3600000 0.0024000
note: replace the tabulation ('\t') with normal whitespace (' ') in the format specifier separator depending on what your meshing software is expecting.
This is the only workaround I could think of:
A = [1.12341234 .12341234 20.12341234 5 10];
% Create a precision mask
maxwidth = 8; % Max width, characters
mask = maxwidth(ones(size(A))) - 1; % Initialize mask, account for decimal
mask(A < 1) = maxwidth - 2;
% Stack the vectors and weave them
temp = [mask(:)';A(:)'];
temp = temp(:);
test = sprintf('%#7.*g ', temp);
Which returns:
test =
1.123412 0.123412 20.12341 5.000000 10.00000
It's an annoying extra step but we can utilize sprintf's ability to take an asterisk in order to refer to an argument in the input list. Due to how my sprintf call and test case are set up, I wove the mask and data together so sprintf sees the precision specifier and data alternating. The temp(:) call isn't necessary, if you pass the original temp matrix to sprintf it will do the same thing since it reads the data column-major. I added it in so the behavior is more explicit.
How to formulate the sprintf call for your actual printing routine will depend on what you're doing, but this should at least help you on your way.
Edit1: To expand, what the above is doing is equivalent to:
a = sprintf('%#7.*g ', temp(1), temp(2));
b = sprintf('%#7.*g ', temp(3), temp(4));
c = sprintf('%#7.*g ', temp(5), temp(6));
d = sprintf('%#7.*g ', temp(7), temp(8));
e = sprintf('%#7.*g ', temp(9), temp(10));
test = [a b c d e];
Edit2: Updated to account for integer values
Edit3: Note that this currently will only work for positive numbers
Suppose that we have this code:
a = pi;
b = pi+2;
c = pi*2.2
out = [a b c]
returns:
out =
3.1416 5.1416 6.9115
I want this output (without rounding values to two decimal):
out =
3.14 5.14 6.91
I don't want print these values. I want see them with 2 decimals here:
Use format bank to get 2 decimal displayed. More details about the format function in the documentation.
If you want to change how the variables are displayed in the variable editor, have a look at this page of the documentation.
In case you just want to use the first 2 decimals, you can add this line to your previous code:
out(:) = str2num(sprintf('%6.2f',out(:))); % 2 = number of decimals
This is not a beautiful solution but it truncates your values to the 2nd decimal and stores it erasing the following decimals. You will still have some zeros at the end (till you fill the selected format for your variable editor as explained above).
So i'm creating a function that is trying to compare decimal numbers with scientific notation. I am trying to round them off and saving them into new variables.
What I did is this...
>> digits(3);
>> Y = vpa(0.000036856864)
Y =
3.69e-5
>> Z = vpa(0.000036857009)
Z =
3.69e-5
>> eq(Y,Z)
ans =
0
Technically the new rounded decimal is saved unto Y and Z, so when I compare the two variables, it gives me 0, but it should be 1. How can I fix this to make sure that the answer equals to 1?
Any help is appreciated!
The values returned by vpa aren't actual numbers - they're symbolic objects that still contain the original value of the number (before rounding). To compare the two, you should convert them back to double:
Y = double(vpa(0.000036856864))
Z = double(vpa(0.000036857009))
eq(Y,Z)
which should return 1