Extracting digits after decimal MATLAB - matlab

I am representing a chaotic number with 15 digits after decimal i.e format long in matlab and i want to extract 3 numbers each containing 5 digits from the chaotic number. i.e if chaotic no. is 0.d1d2...d15 then i want (d1..d5),(d6..d10) & (d11..d15). it is always rounding off.I have written the following code.
num=x(n);
a1=floor(num*10^5);
disp('a1');
disp(a1);
a2=floor(num*10^10-a1*10^5);
disp(a2);
num=floor(num*10^15);
a3=mod(num,100000);
disp('a3');
disp(a3);
and the output is
0.320446597556797
a1
32044
a2
65975
a3
56796
its showing a3 as 56796 but i want 56797.
please help!!!

The problem is, very likely, that each operation you do to extract a group of digits introduces a small error, which is reflected in the last digit.
An alternative approach that avoids this:
num = pi; %// for example
str = num2str(num,'%0.15f'); %// string representation with 15 decimal digits
str = str(find(str=='.')+1:end); %// keep only digits after decimal point
a = base2dec(reshape(str,5,[]).',10); %'// convert string parts into numbers

Try this approach using strings -
n = 0.320446597556797 %// Input decimal number
t1 = num2str(n,'%1.15f')
t2 = strfind(t1,'.')
a = str2num(reshape(t1(t2+1:end),5,[])') %// output as a single matrix
Thanks to #Luis for the reshape idea! Hope you won't mind Luis!

It is probably a rounding error but if you really want those specific values, simply cast to a string and then rip the string apart. Something simple like below
a = 0.320446597556797;
format longg
aStr = num2str(a,'%1.15f');
decimals = regexp(aStr,'\.','Split');
decimals = decimals{2};
a1 = str2double(decimals(1:5));
a2 = str2double(decimals(6:10));
a3 = str2double(decimals(11:15));

Related

Convert a decimal number that is not integer to base 4 in Matlab?

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

Add 1 to the least significant digit of a number in MATLAB

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.

MATLAB: How to discard overflow digits binary addition?

I want to know if it's possible in MATLAB to discard overflow digits in MATLAB when I add two binary numbers.
I've only been able to find how to have a least number of binary digits, but how to I set a maximum number of digits?
For example:
e = dec2bin(bin2dec('1001') + bin2dec('1000'))
That gave me:
e =
10001
How do I get only '0001'?
dec2bin will always give you the minimum amount of bits to represent a number. If you would like to retain the n least significant digits, you have to index into the string and grab those yourself.
Specifically, if you want to retain only the n least significant digits, given that you have a base-10 number stored in num, you would do this:
out = dec2bin(num);
out = out(end-n+1:end);
Bear in mind that this performs no error checking. Should n be larger than the total number of bits in the string, you will get an out of bounds error. I'm assuming you're smart enough to use this and know what you're doing.
So for your example:
e = dec2bin(bin2dec('1001') + bin2dec('1000'));
n = 4, and so:
>> n = 4;
>> e = e(end-n+1:end)
e =
0001
Here is a more robust (but less efficient, I fear) way: What you describe is exactly the modulo operation. A 4-bit binary number is the remainder after a division by 0b10000 = 16. This can be done using the mod function in MATLAB.
>> e = dec2bin(mod(bin2dec('1001') + bin2dec('1000'),16),4)
e =
0001
Note: I added 4 as additional argument to the dec2bin function, so the output will always be 4-bit wide.
This can of course be generalized to any bit width: If you want to add 8-bit numbers, you will need the remainder of the division by 0b1'0000'0000 = 256, for example
>> e = dec2bin(mod(bin2dec('10011001') + bin2dec('10001000'),256),8)
e =
00100001
Or for shorter numbers, e.g. 2-bit wide, it is 0b100 = 4:
>> e = dec2bin(mod(bin2dec('10') + bin2dec('11'),4),2)
e =
01

how to sum digits in a multi-digit number Matlab

I wonder how to sum digits for a multi-digit number in Matlab.
For example 1241= 1+2+4+1 = 8
String-based answer:
>> n = 1241;
>> sum(int2str(n)-48)
ans =
8
The number is first converted to a string representation using int2str, then the ASCII code for '0' (i.e. 48) is subtracted from the ASCII code for each element of the string, producing a numeric vector. This is then summed to get the result.
A = 35356536576821;
A = abs(A);
xp = ceil(log10(A)):-1:1;
while ~isscalar(xp)
A = sum(fix(mod(A,10.^xp)./10.^[xp(2:end) 0]));
xp = ceil(log10(A)):-1:1;
end
this is the numeric approach
This one is the solution is character approach:
A = '35356536576821';
A = char(regexp(A,'\d+','match'));
while ~isscalar(A)
A = num2str(sum(A - '0'));
end
Both, first take the absolute number (strip the minus) then: the numeric one counts with log10() how many digits a number has and through modulus and divisions extracts the digits which are summed, while the char approach convert to numeric digits with implicit conversion of - '0', sums and converts back to string again.
Another all-arithmetic approach:
n = 1241; %// input
s = 0; %// initiallize output
while n>0 %// while there is some digit left
s = s + mod(n-1,10)+1; %// sum rightmost digit
n = floor(n/10); %// remove that digit
end
Youcan use this code
sum(int2str(n)-48)
where n, is your input number.

Using matlab,how to find the last two digits of a decimal number?

How can one find the last two digits of a decimal number using MATLAB?
Example:
59 for 1.23000659
35 for 56368.35
12 for 548695412
There will always be issues when you have a decimal number with many integer digits and fractional digits. In this case, the number of integer and decimal digits decide if we are correct or not in estimating the last two digits. Let's take at the code and the comments thereafter.
Code
%// num is the input decimal number
t1 = num2str(num,'%1.15e') %// Convert number to exponential notation
t1 = t1(1:strfind(t1,'e')-1)
lastind = find(t1-'0',1,'last')
out = str2num(t1(lastind-1:lastind)) %// desired output
Results and Conclusions
For num = 1.23000659, it prints the output as 59, which is correct thanks
to the fact that the number of integer and decimal digits don't add upto
more than 16.
For num = 56368.35, we get output as 35, which is correct again and the
reason is the same as before.
For num = 548695412, we are getting the correct output of 12 because of the
same good reason.
For an out of the question sample of num = 2736232.3927327329236576
(deliberately chosen a number with many integer and fractional digits),
the code run gives output as 33 which is wrong and the reason could be
inferred from the fact that integer and decimal digits add upto a much
bigger number than the code could handle.
One can look into MATLAB command vpa for getting more precision, if extreme cases like the 4th one are to dealt with.
Convert to string and then extract the last two characters:
x = 1.23; % x = 1.23
s = num2str(x); % s = "1.23"
t = s(end-1:end); % t = "23"
u = str2num(t); % u = 23
Note: depending on your specific needs you might want to supply a precision or formatSpec to num2str.
The other two answers are nice and straight forward, but here you have a mathematical way of doing it ;)
Assuming a as your number,
ashift=0.01*a; %shift the last two digits
afloor=floor(ashift); %crop the last two digits
LastDecimals=a-100*afloor; %substract the cropped number form the original, only the last two digits left.
Of course if you have non-natural numbers, you can figure those out too with the same "floor and subtract technique as above.