The calculation of 1/23 * [1 2 3] gives me [0.041667 0.083333 0.125000].
I just want a result like [1/23 2/23 3/23]
You can specify format rat, to always display outputs as rational approximations (applies to both matlab and octave).
format rat
a = 1/23 * [1,2,3]
% a = 1/23 2/23 3/23
Or, you can use that "rat" or "rats" functions, to print (as strings) the rational approximations of a float array:
a = 1/23 * [1,2,3]
% a = 0.043478 0.086957 0.130435
rats(a)
% ans = 1/23 2/23 3/23
As Cris pointed out in the comments, this is simply a representational issue. The underlying floating-point representation of the result does not change. If you wish to work with fractions in a 'mathematical' sense, then you need to go about this a different way (possibly symbolic package, or dealing with numerators and denominators manually).
Related
I currently have the following code:
count = 20;
n = zeros(count, 1);
P = zeros(count, 1);
for i = 1:count
n(i) = i;
P(i) = sym(i)^i + (sym(1-i))^(i-1);
if i == (count)
T = table(n,P)
end
end
This gives me a table with a set of values. However, some of the values are losing precision because they have too many digits.
I am aware that MATLAB allows for up to 536870913 digits of precision. How do I make my table values not lose precision?
Note: if I were to just do the following operation (for example): sym(200)^2010, I would get the full precision value, which has 4626 digits. Doing this for table values doesn't seem to work, though, for some strange reason.
If someone could please help me with this I would be extremely grateful as I have been struggling with this for several hours now.
As #Daniel commented, the problem is that you are casting to double when storing it in P. MATLAB only has the precision you mention when using symbolic variables, but when you get into the numerical world, you can only store a finite amount of precision.
To be exact, once you define P as a double (zeros returns a double vector), the biggest integer you can store such that all of its smaller integers are precise is 2^53, way smaller than your P(20). This means that any integer bigger than 2^53 is not ensured to be precise on a double valued vector.
Your solution is thus to avoid casting, to store the variable on a sym type P. Note that the above also applies to later maths. If you plan to use this variable in some equation, remember that when you pass it to numerical form, you will lose precision. Often this does not matter, as the precision lost is very small, but you should know it.
If you want to learn more about how numerical precision work on computers, I suggest reading the following Q&A: Why is 24.0000 not equal to 24.0000 in MATLAB?
Sym solution:
count = 20;
n = zeros(count, 1);
P = sym('integer',[count, 1]);
for i = 1:count
n(i) = i;
P(i) = sym(i)^i + (sym(1-i))^(i-1);
if i == (count)
T = table(n,P)
end
end
returns
>> T.P(20)
ans =
102879180344339686410876021
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
realmax on my machine is:
1.7977e+308
I know I have to write my code in a way to avoid long integer calculations, but is there any way to increase the limit?
I mean something like gmp library in C
You may find vpa (variable- precision arithmetic) helpful:
R = vpa(A) uses variable-precision arithmetic (VPA) to compute each element of A to at least d decimal digits of accuracy, where d is the current setting of digits.
R = vpa(A,d) uses at least d significant (nonzero) digits, instead of the current setting of digits.
Here's an example how to use it:
>> x = vpa('10^500/20')
ans =
5.0e498
Note that:
The output x is of symbolic (sym) type. Of course, you shouldn't convert it to double, because it would exceed realmax:
>> double(x)
ans =
Inf
Use string input in order to avoid evaluating large input values as double. For example, this doesn't work
>> vpa(10^500/20)
ans =
Inf
because 10^500 is evaluated as double, giving inf, and then is used as an input to vpa.
newT = [b(i) d(i) a(i) z(i)];
newT, b(i), a(i)
Prints
newT =
123 364 123 902
ans =
1.234e+02
ans =
1.234e+02
What is the problem here? Why are the first and third entry in newT rounded to integer values? Why aren't they correctly assigned?
Unlike most other programming languages, integer types in Matlab take precedence over floating point types. When you combine them, either through concatenation or arithmetic, the floating point values are implicitly narrowed to integers, instead of the integers being widened to floating point.
>> int32(3) + 0.4
ans =
3
>> [int32(3) 0.4]
ans =
3 0
This is for historical reasons, because (IIRC) Matlab originally didn't have support for integers at all, so all numeric constants in Matlab produce double values, and the promotion rules were created to make it possible to mix integer types with floating-point constants.
To fix this, explicitly convert those int types to doubles before concatenating.
newT = [b(i) double(d(i)) a(i) double(z(i))];
I'm working in Matlab using Non-negative Matrix factorization to decompose a matrix into two factors. Using this I get from A two double precision floating point matrices, B and C.
sample results are
B(1,1) = 0.118
C(1,1) = 112.035
I am now trying to modify specific bits within these values but using the bitset function on either values I get an error because bitset requires unsigned integers.
I have also tried using dec2bin function, which I assumed would convert decimals to binary but it returns '0' for B(1,1).
Does anyone know of any way to deal with floats at bit level without losing precision?
You should look into the typecast and bitset functions. (Doc here and here respectively). That lets you do stuff like
xb = typecast( 1.0, 'uint64' );
xb = bitset( xb, 10, 1 );
typecast( xb, 'double' );
The num2hex and hex2num functions are your friends. (Though not necessarily very good friends; hexadecimal strings aren't the best imaginable form for working on binary floating-point numbers. You could split them into, say, 8-nybble chunks and convert each to an integer.)
From the MATLAB docs:
num2hex([1 0 0.1 -pi Inf NaN])
returns
ans =
3ff0000000000000
0000000000000000
3fb999999999999a
c00921fb54442d18
7ff0000000000000
fff8000000000000
and
num2hex(single([1 0 0.1 -pi Inf NaN]))
returns
ans =
3f800000
00000000
3dcccccd
c0490fdb
7f800000
ffc00000