Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

log question

JohnNichols
Valued Contributor III
1,871 Views
log(float(num))

if num is an integer, why not have a log function that can take an integer?

0 Kudos
1 Solution
jimdempseyatthecove
Honored Contributor III
1,529 Views

See:

IEEE_SET_ROUNDING_MODE
 you can set to IEEE_DOWN, IEEE_NEAREST, IEEE_TO_ZERO, IEEE_UP, or IEEE_OTHER
IEEE_RINT using above mode
 
Jim Dempsey
 

View solution in original post

0 Kudos
21 Replies
JohnNichols
Valued Contributor III
1,774 Views
NINT(0.49999999)

This rounds to 1, 

NINT(0.49999998)

this rounds to zero. 

I understand why - likely - but it is interesting. 

0 Kudos
AlHill
Super User
1,767 Views

The forum software provides an EDIT function so users do not have to do multiple posts.   What is interesting is that it is not used when it should be.

 

Doc (not an Intel employee or contractor)
[Windows 11 is the new Vista]

0 Kudos
JohnNichols
Valued Contributor III
1,756 Views

Sometimes the truth is obvious, thank you.  

I would not say the new Vista.  It is interesting and a work in progress.  It has a few interesting features. 

0 Kudos
Steve_Lionel
Honored Contributor III
1,740 Views

It would be clutter in the language to have integer versions of intrinsics typically used only on reals. The only motivation to do so is if there would be some implementation advantage, and here you'd just convert to real anyway.

As for NINT(0.49999999), I'm sure you know that the nearest representable value to this is .5, which rounds up to 1.

JNichols
New Contributor I
1,688 Views

I think the language could adjust to a function - let us call it ilog.  Things change and sometimes change is good.  

I know that, but actually the code should catch that and not return 1.  

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,679 Views

Catch what? That decimal value gets converted to binary 0.5 exactly.

Change for change's sake is not good. As it is, the language forces you to acknowledge that what you're doing is unusual.

mecej4
Honored Contributor III
1,641 Views

The flaw in JohnNichols' arguments is that his expectations are based on the behavior of base-10 real numbers. A processor that uses base-2 floating point numbers is not likely to meet those expectations.

What should the statement

print *, 0.49999999 .LT. 0.5, 'JNichols' .eq. 'JohnNichols'

 output?

0 Kudos
JohnNichols
Valued Contributor III
1,602 Views

As I said in the beginning, I understand why it does it. 

It is a variation on the bunny hop problem from pure math, the bunny never reaches 1.  In the limit, she does, but in a infinite world she does not, so we have a finite world, we can now peacefully disagree on how NINT should handle the last hop.  It is not a big deal, it was just interesting because I ran into and thought it was amusing from a pure math viewpoint, like a hidden easter egg.  

I was looking yesterday on the Fortran Language Discourse site, someone has suggested that ifthen is added as a command to Fortran where it is the EXCEL if statement with a different name.  My internal thought was "terrible idea", but I did not express that opinion, there is a committee to decide that. 

If we cannot laugh at interesting things, then there is something wrong with the world. 

0 Kudos
JNichols
New Contributor I
1,581 Views

NINT(A) rounds its argument to the nearest whole number.

if the number starts with .4   == whatever follows is not relevant no matter how many 9's there are.  The first digit must be 0 in the binary and so it rounds to 0.  

There is a website that does the same calculation and it does not make a mistake, it just stops adding the '9s.  

NINT should treat the number as a series of ints 0-9 and only check till it has reached a conclusion.  .4?????????????????????????? is conclusive irrespective of ???????????????????????????????  

Unless I am mistaken. 

0 Kudos
Steve_Lionel
Honored Contributor III
1,552 Views

@JNichols wrote:

NINT(A) rounds its argument to the nearest whole number.

if the number starts with .4   == whatever follows is not relevant no matter how many 9's there are.  The first digit must be 0 in the binary and so it rounds to 0.  

Unless I am mistaken. 


You are mistaken. I thought I had explained this earlier, but I'll try again.

In the following program I look at how far the binary single-precision value is from a double-precision representation of the same decimal value.

 

real(4) :: x
real(8) :: xx
integer(4) :: ix
x = 0.49999999
xx = 0.49999999_8
ix = transfer(x,ix)
write (*,'(Z8.8,1X,F20.17,1X,G0.5)') ix,x,abs(xx-real(x,8))
ix = ix - 1
x = transfer(ix,x)
write (*,'(Z8.8,1X,F20.17,1X,G0.5)') ix,x,abs(xx-real(x,8))
end

 

Compile and run this and I get:

 

3F000000  0.50000000000000000 .10000E-07
3EFFFFFF  0.49999997019767761 .19802E-07

 

What this shows us is that 0.5 is closer to the original decimal value than the next lowest representable value, so it is the correct choice.

Once the decimal value is converted to single-precision, the leading digit is 5, not 4. 

Many years ago, (now retired) DEC developer Dave Eklund wrote a series of articles titled "The Perils of Real Numbers". Read them here:

The Perils of Real Numbers (Part I) - Intel Community

The Perils of Real Numbers (Part 2) - Intel Community

The Perils of Real Numbers (Part 3) - Intel Community

avinashs
New Contributor I
1,564 Views

When I first saw the post from @JohnNichols , it reminded me of some of my own misconceptions about the Fortran intrinsic functions. My thoughts (or misconceptions):

1. I thought all Fortran math intrinsics (where applicable) are overloaded for integer types as well.

2. If a function defined as

function mysqrt(d) result(r)
real(kind = :: d, r
r = sqrt(d)
end function mysqrt

is passed an integer, the integer would be promoted to double precision just as it would in the statement d = 1.

3. I often have to use sqrt(n), where n is the length of a vector, and this is where what is needed for compatibility is sqrt(real(n, kind = 8)). A similar situation to taking the logarithm of an integer.

4. The C/C++ math functions do accept integer arguments.

5. In legacy Fortran 77 codes, the promotion of integer to double was accepted by the compilers. Interface checking has to be turned off for many of those older codes to work.

5. A similar inconvenience for me is the MERGE function where I often need to use something on the lines of

lda = merge('dense', 'band', matrix_type == 1)

which fails because the character lengths are unequal. Would be convenient to have the function accept varying character lengths.

6. Over the years, I have built a module with my own version of many of these intrinsic functions including MINVAL, MAXVAL, MINLOC, MAXLOC, MERGE, ANY, ALL among others to fit my needs. These are a bit more complicated to implement each time in code.

0 Kudos
avinashs
New Contributor I
1,559 Views

I will add (as I have done previously) that the forum posts do not accept (kind = X) for some reason, which is why = 8 is missing in the code above.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,511 Views

>>I will add (as I have done previously) that the forum posts do not accept (kind = X) for some reason, which is why = 8 is missing in the code above.

When inserting source code, click on the "..." to expose additional options, then click on the "</>" for source code. Use the pull-down to select language (C++, Fortran, Plain Text, ...) then enter your source code snip. After entering, I usually have to Tab,Enter to resume forum text entry.

Apparently the web editing system was written for a non-programmer's forum... and has caused several inconveniences to us users. A pet peeve of mine is to not have the posts listed in non-tree chronological order together with a sequence number (for use in reference). Current method has option for chronological order... BUT within branch. This makes it problematic in locating new posts for a thread (making you find, then parse through each branch, if any). 

A second, grave oversight, is not being able to (successfully) select AND COPY just the text of a source code inserted block of sample code. As it stands now, selection works but copy unselects prior to copy.

Jim Dempsey

0 Kudos
mecej4
Honored Contributor III
1,543 Views

Misconceptions on the differences between decimal and binary floating point arithmetic and accumulation of errors of this nature caused a missile interception system (the 1970s-computer in this system had 24 bits of precision) to fail to intercept an incoming missile and as a result 28 soldiers died.

0 Kudos
JNichols
New Contributor I
1,501 Views

Let me say this clearly, I understand and accept as "you have to lump it" the ways of decimal and binary numbers.  

However, as an engineer who looks at life safety and I did not raise this issue, I make the clear point:

NINT(0.49999999)

takes this number and returns one.  As I stated in my first post, I understand why it does that and I observed it is interesting.  I was just pointing out the oddities of decimal to binary.  I was also pointing out that I typed the number into NINT I did not do 

real a
a = 0.4999999
NINT(a) 

In this case, we accept the Fortran limitation, but in a better world, the NINT would treat the number I typed in as a string and check for the rare occurrence when under these circumstances the translation would provide an error in NINT.  This is a minor coding issue for a compiler.  

In the 1950's I accept this was not possible when NINT was invented, but it is possible now.  

We all work with limitations, as Clint Eastwood used to say, but a modern compiler should pick up oddities.  If we look at the number of steps in the binary numbers from 0 to 0.5 with accuracy of the number I have given this interesting observation occurs with a frequency of less than 1 in a million % chance, i.e. almost never.  

We do not live in a perfect world, and a programmer has to know their limitations, but this is a bit obvious and I do not think this should be a lump in the road.  

The people who write the compiler are perfectly free to continue to leave it as is and I am not going to stop using the compiler. 

The problem with free speech is of course free and speech. But I would rather spend time here, even with the comments, than in a lot of other places. 

And the point of the world is that there are people who like Toohey's New (beer) and there are some who do not, admittedly a vanishing small percentage, as my father once observed, but I cannot stand the stuff.  As my father once observed, when standing in the bar at the Lake Macquarie Yacht Club, son what you drink can best be described as toxic sludge, served only in 3 pubs in the world, near the wharves, and drunk only by old union people who are probably red's.  

I smiled.  He is of course correct.   

0 Kudos
AlHill
Super User
1,475 Views

Interesting.  I have never known anyone who would admit to hanging around the Lake Macquarie Yacht Club.

 

Doc (not an Intel employee or contractor)
[Windows 11 is the new Vista]

0 Kudos
JohnNichols
Valued Contributor III
1,466 Views

Very  true.  Thank you for the reminder of the small crowd I sail with.  Some of things their wives say about them are interesting, but none of them can be accused of knowing what Fortran is at all.  

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,530 Views

See:

IEEE_SET_ROUNDING_MODE
 you can set to IEEE_DOWN, IEEE_NEAREST, IEEE_TO_ZERO, IEEE_UP, or IEEE_OTHER
IEEE_RINT using above mode
 
Jim Dempsey
 

0 Kudos
JohnNichols
Valued Contributor III
1,449 Views
0 Kudos
andrew_4619
Honored Contributor II
1,481 Views

Maybe rather than typing NINT(0.49999999) you should have typed 0 if that is what you wanted it to be. As it is you type a very long winded version of 1. 

 

 

0 Kudos
Reply