Fortran [Fortran] Rounding up Random Numbers

AI Thread Summary
The discussion revolves around generating an array of random 1s and 0s using Fortran 95. The original code attempts to round random numbers generated between 0 and 1 using the NINT function, but it incorrectly assigns values to only the last element of the integer array, leading to garbage values for the others. The suggested solution involves using a loop to ensure all elements are populated correctly. Additionally, there are concerns about potential segmentation faults due to incorrect indexing. A revised program successfully generates a 10x10 matrix of random 0s and 1s, and suggestions for improving output formatting are also discussed, emphasizing the need for appropriate format descriptors to enhance readability. Overall, the thread highlights common pitfalls in Fortran programming and offers solutions for effective random number manipulation and output formatting.
Lukejambo
Messages
13
Reaction score
0
Hi,

So I'm writing a programme in Fortran95 atm and I want to produce an array of 1s and 0s.

I've used a random number and random seed generator to produce 10 numbers between 0 and 1 and I want to use a NINT statement to round these random numbers to 0 or 1.

However when I try this the rounded numbers are very large which I know shouldn't happen...

Any help will be much appreciated.
 
Technology news on Phys.org
Perhaps you could show your work, so we can critique it.
 
Thanks for the quick reply Dave! Here is the code:

program random
implicit none
integer :: n
real :: a(10)
integer :: i(10)

n=10
call random_seed()
call random_number(a)

write(6,*) (a(n),n=1,10)
write(6,*) ''

i(n) = NINT(a(n))

write(6,*) (i(n),n=1,10)

end program random
 
And the output?

If you would put in some debugging lines, of particular interest would be the values of a(n) just before the NINT function.
 
  • Like
Likes Lukejambo
Lukejambo said:
Thanks for the quick reply Dave! Here is the code:

program random
implicit none
integer :: n
real :: a(10)
integer :: i(10)

n=10
call random_seed()
call random_number(a)

write(6,*) (a(n),n=1,10)
write(6,*) ''

i(n) = NINT(a(n))

write(6,*) (i(n),n=1,10)

end program random
I think it's this line: i(n) = NINT(a(n)). I believe that all this is doing is setting i(10) to the rounded value in a(10). i(1), i(2), ..., i(9) will have garbage values.
If you want all 10 elements of your i array to have values, do this:
Code:
do n = 1, 10
   i(n) = NINT(a(n))
end do
 
  • Like
Likes Lukejambo
Mark44 said:
I think it's this line: i(n) = NINT(a(n)). I believe that all this is doing is setting i(10) to the rounded value in a(10). i(1), i(2), ..., i(9) will have garbage values.
It's even worse than that, as n has a value of 11 after the loop in write(6,*) (a(n),n=1,10). The original code could produce a segmentation fault.

Mark44 said:
If you want all 10 elements of your i array to have values, do this:
Code:
do n = 1, 10
   i(n) = NINT(a(n))
end do
In Fortran 95, the loop can be implicit:
Code:
   i = NINT(a)
 
  • Like
Likes Lukejambo
Thanks very much for your help, I've managed to produce a matrix of ones and zeroes which are all randomly placed.
 
It would be awesome if you posted your result, so that others may learn.
 
Here is the code:! This programme produces a 10x10 matrix of 0's and 1's using the random number and random seed function.

program randomex
implicit none
integer :: n
real :: a(100)
integer :: i(100)
open(unit=20, file='randomex')n=100
call random_seed()
call random_number(a)

! Below writes the matrix of random numbers, all between 0 and 1.

write(6,'(10f5.3)') (a(n),n=1,100)
write(20,'(10f5.3)') (a(n),n=1,100)
write(6,*) ''

! Rounding these random numbers up/down.

i = NINT(a)

! Writing the matrix to screen.

write(6,'(10i2)') (i(n),n=1,100)
write(20,'(10i2)') (i(n),n=1,100)
write(6,*) ''end program randomex
 
  • #10
And the output:0.7180.3280.1310.5310.1930.5790.1660.4610.7620.613
0.7380.1280.4020.4000.2200.9330.0800.7640.9990.505
0.6310.6970.8230.9630.6980.4480.9360.3010.9390.489
0.9860.4930.3490.4180.1700.8120.8390.0900.4720.117
0.4600.9490.5750.1400.0460.8190.8350.4690.0500.043
0.6670.3730.0860.7360.2130.4890.0480.2610.5900.725
0.3230.7440.3710.1320.5550.6510.4830.4160.3020.064
0.8560.3270.6190.4030.6840.0930.0150.6130.3940.412
0.1760.7080.7980.8920.9990.4480.9090.7350.3680.634
0.0250.6520.9440.8540.3770.2880.5530.1050.0340.424

1 0 0 1 0 1 0 0 1 1
1 0 0 0 0 1 0 1 1 1
1 1 1 1 1 0 1 0 1 0
1 0 0 0 0 1 1 0 0 0
0 1 1 0 0 1 1 0 0 0
1 0 0 1 0 0 0 0 1 1
0 1 0 0 1 1 0 0 0 0
1 0 1 0 1 0 0 1 0 0
0 1 1 1 1 0 1 1 0 1
0 1 1 1 0 0 1 0 0 0
 
  • #11
@Lukejambo, do you still have a question? Your output suggests that your program is working as intended, although the output of the unrounded numbers is harder to read than it should be. For the real numbers, you are printing them using this write statement
Code:
write(6,'(10i2)') (i(n),n=1,100)
Here you are using a format edit descriptor of 10i2 to print them in fields of 10 integers (i2), using a width of two columns for each. Since each number takes up more than two columns, the compiler overrides your I2 format descriptor.

A better choice would be to print them using a real format descriptor such as F10.8 for each number, followed by a space, X.

I think this would work, but I don't currently have a Fortran compiler to test it on.
Code:
write(6, '5(F10.2, X)') (i(n),n=1,100)
 
  • #12
Mark44 said:
For the real numbers, you are printing them using this write statement
Code:
write(6,'(10i2)') (i(n),n=1,100)

You got the wrong line there, he is using
Fortran:
write(6,'(10f5.3)') (a(n),n=1,100)

But you are correct that it would be better to add a space
Fortran:
write(6,'(10(f5.3,x))') (a(n),n=1,100)
 
  • #13
Right you are @DrClaude, I was thinking the last two write statements created the output he posted -- the first for the raw numbers, and the second for the rounded ints.
 

Similar threads

Back
Top