How can i get up to 7 significant figures of my result in FORTRAN90? - fortran90

INTEGER, PARAMETER :: SINGLE=SELECTED_REAL_KIND(7)
REAL(KIND=SINGLE) :: K
REAL::X
...
K=X
WRITE(*,*) K
When i write 5 or 6 inside SELECTED_REAL_KIND, it outputs six significant figures but when i try 7, it outputs more than 7. Can you tell me why? Where i got it wrong? Assigning is problematic?
With 5 and 6 output-> 1.39256
With 7 output-> 1.3925623893
Okey I'm asking a simple question. How can i just output 7 significant digits of this number 1.3925623893
?

From gfortran's documentation:
SELECTED_REAL_KIND(P,R) returns the kind value of a real data type with decimal precision of at least P digits
The at least is important. Floating point numbers are most of the time stored using 4 bytes (single precision) or 8 bytes (double precision) and that's it. That's going from asking 6 to 7 significant figures actually adds even more figures: you switched from single to double precision.
What you really want is have a real large enough to store the precision you want, and you already did that correctly, then display only 7 significant figures using a format like:
write(*,'(F12.7)') K

Related

How does Matlab store this large of a number with only 64 bits?

The largest number in double precision (that is, 64 bit) floating point arithmetic is
1.111...110 x 2^(512) (where there are 51 1's after the radix point). This number is less than 2 x 2^(512) == 2^(513) == 8^(171) < 10^(171). Therefore, when I assign x = 10^(171), I expect that x will be stored as Inf. However, this is not the case. Calling x in the interactive console displays 1.0000e+171. The only explanation I could think of is that Matlab uses more than 64 bits to store x. But a quick check of whos x reveals that x is stored in 8 bytes.
In fact, the largest power of 10 which will not be stored as Inf is 10^308.
Can someone please explain what is going on here?
I'm sorry, I made a simple mistake here. In 64 bit arithmetic, 11 bits are used to encode the exponent. Therefore we have 2^(11) = 2048 possible exponents, and so they range from -1023 to 1024, not from -511 to 512 like I thought. Therefore the largest number in 64 bit arithmetic is $1.111...110 x 2^(1024)$, which is in fact (with the exponent having 3 significant digits) 10^(308.6), corroborating my experimental results.

Machine Epsilon: MatLab vs Maple

I'm learning about machine epsilon in single and double precision and comparing values from different programs. For example, in matlab the following code:
>> format long
>> eps
gives 2.220446049250313e-16. But the following code in Maple:
> readlib(Maple_floats);
> evalhf(DBL_EPSILON);
> quit;
gives -15
.2220446049250314 10 (where -15 is exponent).
There is a slight difference in output between the two programs. Maple appears to round up from 3 to 4. What is the reason for this difference?
Note that Maple (and Matlab) are showing you a radix-10 representation of a hardware double precision floating point number.
So perhaps you should be more concerned with the underlying hardware double precision value.
> restart:
> kernelopts(version);
Maple 2015.0, X86 64 LINUX, Feb 17 2015, Build ID 1022128
> X:=Vector(1,datatype=float[8]): # double precision container
> p:=proc(x) x[1]:=DBL_EPSILON; end proc:
> evalhf(p(X)):
> lprint(X[1]);
HFloat(.222044604925031308e-15)
> printf("%Y\n", X[1]);
3CB0000000000000
That last result is "formatted in byte-order-independent IEEE hex dump format (16 characters wide)", according to the documentation.
So, what does Matlab give you when you printf its eps in the equivalent format? A quick web-search seems to reveal that it'll give 3CB0000000000000 alongside that 2.220446049250313e-16 you saw.
In other words: the hardware double precision representation is the same in both systems. They are representing it differently in base 10. Note that the
base 10 value displayed by Maple has 18 decimal places. The digits past the 15th are artefacts of a sort, stored so that in general internally stored numbers can round-trip correctly for repeated conversion both ways. Note that hardware double precision relates to something between 15 and 16 decimal places. So if you want to compare between the two systems you could (and likely should) compare the stored hardware double precision values and not the base 10 representations past the 15th place.

exponential function with large argument in matlab [duplicate]

This question already has answers here:
How to compute an exponent in matlab without getting inf?
(3 answers)
Closed 7 years ago.
I've got one problem for a longer time and I'd be really grateful if you could help me somehow...
I have a code in MATLAB (version R2012a) where I compute some exponential functions using MATLAB's fuction exp. This means that I have something like this:
y = exp(x);
However, when this "x" is larger than a certain number, the result ("y") is infinity; when "x" is smaller than a certain number, the result is 0. As said on the MathWorks' website:
Numerical exceptions may happen, when the absolute value of the real
part of a floating-point argument x is large. If ℜ(x) < -7.4*10^8,
then exp(x) may return the truncated result 0.0 (protection against
underflow). If ℜ(x) > 7.4*10^8, then exp(x) may return the
floating-point equivalent RD_INF of infinity.
My problem is quite obvious - my "x" are pretty large so I receive infinities and zeros instead of results I need. My question is - how do I get the real results? Thanks in advance for help!
Use vpa with a string input:
>> exp(1000)
ans =
Inf
>> vpa('exp(1000)')
ans =
1.9700711140170469938888793522433*10^434
Note the result of vpa is of class sym.
A variable in any language is stored in a certain amount of bytes in the computer's memory. The more bytes used to hold a variable type, the more precise of a result that variable can hold. If you are using integers, the biggest type uses 64 bytes and is uint64. This is an unsigned integer (meaning it can only be positive) that can range from 0 to 18,446,744,073,709, 551,615. If you need decimals, try using vpa.

mod() operation weird behavior

I use mod() to compare if a number's 0.01 digit is 2 or not.
if mod(5.02*100, 10) == 2
...
end
The result is mod(5.02*100, 10) = 2 returns 0;
However, if I use mod(1.02*100, 10) = 2 or mod(20.02*100, 10) = 2, it returns 1.
The result of mod(5.02*100, 10) - 2 is
ans =
-5.6843e-14
Could it be possible that this is a bug for matlab?
The version I used is R2013a. version 8.1.0
This is not a bug in MATLAB. It is a limitation of floating point arithmetic and conversion between binary and decimal numbers. Even a simple decimal number such as 0.1 has cannot be exactly represented as a binary floating point number with finite precision.
Computer floating point arithmetic is typically not exact. Although we are used to dealing with numbers in decimal format (base10), computers store and process numbers in binary format (base2). The IEEE standard for double precision floating point representation (see http://en.wikipedia.org/wiki/Double-precision_floating-point_format, what MATLAB uses) specifies the use of 64 bits to represent a binary number. 1 bit is used for the sign, 52 bits are used for the mantissa (the actual digits of the number), and 11 bits are used for the exponent and its sign (which specifies where the decimal place goes).
When you enter a number into MATLAB, it is immediately converted to binary representation for all manipulations and arithmetic and then converted back to decimal for display and output.
Here's what happens in your example:
Convert to binary (keeping only up to 52 digits):
5.02 => 1.01000001010001111010111000010100011110101110000101e2
100 => 1.1001e6
10 => 1.01e3
2 => 1.0e1
Perform multiplication:
1.01000001010001111010111000010100011110101110000101 e2
x 1.1001 e6
--------------------------------------------------------------
0.000101000001010001111010111000010100011110101110000101
0.101000001010001111010111000010100011110101110000101
+ 1.01000001010001111010111000010100011110101110000101
-------------------------------------------------------------
1.111101011111111111111111111111111111111111111111111101e8
Cutting off at 52 digits gives 1.111101011111111111111111111111111111111111111111111e8
Note that this is not the same as 1.11110110e8 which would be 502.
Perform modulo operation: (there may actually be additional error here depending on what algorithm is used within the mod() function)
mod( 1.111101011111111111111111111111111111111111111111111e8, 1.01e3) = 1.111111111111111111111111111111111111111111100000000e0
The error is exactly -2-44 which is -5.6843x10-14. The conversion between decimal and binary and the rounding due to finite precision have caused a small error. In some cases, you get lucky and rounding errors cancel out and you might still get the 'right' answer which is why you got what you expect for mod(1.02*100, 10), but In general, you cannot rely on this.
To use mod() correctly to test the particular digit of a number, use round() to round it to the nearest whole number and compensate for floating point error.
mod(round(5.02*100), 10) == 2
What you're encountering is a floating point error or artifact, like the commenters say. This is not a Matlab bug; it's just how floating point values work. You'd get the same results in C or Java. Floating point values are "approximate" types, so exact equality comparisons using == without some rounding or tolerance are prone to error.
>> isequal(1.02*100, 102)
ans =
1
>> isequal(5.02*100, 502)
ans =
0
It's not the case that 5.02 is the only number this happens for; several around 0 are affected. Here's an example that picks out several of them.
x = 1.02:1000.02;
ix = mod(x .* 100, 10) ~= 2;
disp(x(ix))
To understand the details of what's going on here (and in many other situations you'll encounter working with floats), have a read through the Wikipedia entry for "floating point", or my favorite article on it, "What Every Computer Scientist Should Know About Floating-Point Arithmetic". (That title is hyperbole; this article goes deep and I don't understand half of it. But it's a great resource.) This stuff is particularly relevant to Matlab because Matlab does everything in floating point by default.

Matlab floor bug? [duplicate]

This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 5 years ago.
I think I found a bug in Matlab. My only explanation is, that matlab calculates internally with other values than the ones which are displayed:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(ans)
ans =
3
Displayed code is an output from the Matlab console. calc(x,y) is just an array of double values.
MATLAB uses the standard IEEE floating point form to store a double.
See that if we subtract off a tiny amount from 4, MATLAB still diplays 4 as the result.
>> format long g
>> 4 - eps(2)
ans =
4
In fact, MATLAB stores the number in a binary form. We can see the decimal version of that number as:
>> sprintf('%.55f',4-eps(2))
ans =
3.9999999999999995559107901499373838305473327636718750000
Clearly MATLAB should not display that entire mess of digits, but by rounding the result to 15 digits, we get 4 for the display.
Clearly, the value in calc(1,11) is such a number, represented internally as less than 4 by just a hair too little that it rounds to 4 on display, but it is NOT exactly 4.
NEVER trust the least significant displayed digit of a result in floating point arithmetic.
Edit:
You seem to think that 3.999999999999999 in MATLAB should be less than 4. Logically, this makes sense. But what happens when you supply that number? AH yes, the granularity of a floating point double is larger than that. MATLAB cannot represent it as a number less than 4. It rounds that number UP to EXACTLY 4 internally.
>> sprintf('%.55f',3.9999999999999999)
ans =
4.0000000000000000000000000000000000000000000000000000000
What you got was a value really close to but lower than 4, and even with format long Matlab has to round to the 15th digit to display the number.
Try this:
format long
asd = 3.9999999999999997 %first not-9 #16th digit
will print 4.000000000000000. Anyone who doesn't know the actual value of asd based on what gets visualized would guess it is at least 4, but running
asd >= 4
gives 0, and so floor(asd) returns 3.
So is a matter of how Matlab rounds the displayed output, the true value stored in the variable is less than 4.
UPDATE:
if you go further with the digits, like 18x9:
>> asd = 3.999999999999999999
asd =
4
>> asd == 4
ans =
1
asd becomes exactly 4! (notice it doesn't display 4.000000000000000 anymore) But that's another story, is no more about rounding the number to have a prettier output, but about how the floating point arithmetic works... Real numbers can be represented up to a certain relative precision: in this case the number you gave is so close to 4 that it becomes 4 itself. Take a look to the Python link posted in the comment by #gokcehan, or here.
I won't go over the problem, instead I will offer a solution: Use the single function:
B = single(A) converts the matrix A to single precision, returning that value in B. A can be any numeric object (such as a double). If A is already single precision, single has no effect. Single-precision quantities require less storage than double-precision quantities, but have less precision and a smaller range.
This is only meant to be a fix to this particular issue, so you would do:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(single(ans))
ans =
4