I want to calculate julian day for just one year (not from 4713 BC!). For example, If it is 3 of March, it will give as a result the number 62 If February has 28 days, and 63 if it has 29. Until now, I have written the following code in Fortran 95, which unfortunately gives wrong result. Could you please help me debug it?
program task
!============================
!filename: task.f95
implicit none
integer day, sum_month, i, month(12), jd, year, mon
month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
write(6,*) "Give day"
read(5,*) day
write(6,*) "Give mon"
read(5,*) mon
write(6,*) "Give year"
read(5,*) year
sum_month = 0
if (mod(year,4)==0 .and. mod(year,100)/=0) then
do i = month(1), mon-1
sum_month = sum_month + month(1) + day + 1
end do
else
do i = month(1), mon-1
sum_month = sum_month + month(1) + day
end do
end if
write(6,*) sum_month
end program task
This loop
do i = month(1), mon-1
sum_month = sum_month + month(1) + day + 1
end do
and the other one like it, is seriously broken. Every time you call it month(1)==31 and mon is likely to be between 1 and 12 (inclusive). So the program will try to execute, for (for example) mon==12
do i = 31,12
and under the rules of Fortran this loop will execute 0 times. I'm almost certain you should write:
do i = 1, mon-1
sum_month = sum_month + month(i) ...
Fix that, sort out the rest of your code, and you'll probably fix it without further help.
EDIT:
Your code is getting worse ! Well, it was getting worse until VladimirF rolled back your latest changes. Do as he and I have suggested. Ask a new question concerning your current problem.
You're not being careful enough about the difference between your variable mon (which you use to hold the number of the month input by the user) and month (which is the array you use to hold the number of days in each month of the year).
These statements
write(6,*) "Give mon"
read(5,*) month(i)
will read the value which belongs in mon and put it into month(i). Or rather, that's what it tries to do but at that place in the code i doesn't have any value and the code attempts to write it into some arbitrary location in the computer's memory -- this is what a segmentation fault is and this is a great way to generate one. Don't do that !
You're going to have a problem later too, when your code reaches
do i = 1, month(i)-1
Go back to the top of my answer and ask yourself What value does month(i) have when this line of code is executed ?
Related
Alright, so I had an assignment in c++ where the user was to input a day and if the day was less than 10, the program would have to output a 0 in front of it. If the day was greater than 10, the program would output the day. An example would be if the user inputs 5, the program would output 05. If the user inputs 24, the program would output 24. My question is how do we define the 0 in front of the 5. This is the snippet of code of which I attempted but to no avail.
if (day < 10){
f = 0 << day;
}
else {
f = day;
}
This is the statement I'm struggling with: f = 0 << day;
Any help would be great.
Thanks.
You can simply write:-
if(day<10)
{
cout<<"0"<<day;
}
else cout<<day;
If you have any queries, please let me know
Use printf to format your output
Ex:
printf("%02d", day);
I have a problem and probably it is very simple. There are sales values of 2 years for some markets in my data. I'm trying to calculate annual growths so I divide 2019 value of a market by 2018 value and then subtract -1. (Example: 2018 sales: $100, 2019 sales: $200. Growth is [(200/100)-1]= 1= %100) But some markets were 0 in 2018 and started to operate in 2019. Therefore, the growth must be +%100. But it gives -%100.
YTD19vs18 = (DIVIDE(SUM(YTDPerformans[YTD 2019]);SUM(YTDPerformans[YTD 2018])))-1
Sure it gives -1 because thats the result of the calculation
(0 / 200) - 1 = -1
You can include a check for this case. Somthing like if the previous year is zero return always 1 = 100%:
YTD19vs18 = IIF(
YTDPerformans[YTD 2018] = 0;
1;
DIVIDE(SUM(YTDPerformans[YTD 2019]);
SUM(YTDPerformans[YTD 2018]))
)-1
)
I made this operator for class where I store date, it is supposed to add given number of days to date and convert it back to human format
CDate CDate::operator+(const int x)
{
time_t t;
struct tm tmp = {0};
struct tm newtime = {0};
tmp.tm_year = timeinfo.tm_year;
tmp.tm_mon = timeinfo.tm_mon;
tmp.tm_mday = timeinfo.tm_mday + x;
t = mktime(&tmp);
newtime = *(localtime(&t));
return CDate(newtime.tm_year,newtime.tm_mon,newtime.tm_mday);
}
problem is it compute date 3 days higher that it should
concrete problem is, I have date 2000-01-02 (year-month-day) and i try to add 1500 days, expected result is 2004-02-10 but I am getting 2004-02-13
check
what am I doing wrong here?
my code:
http://pastebin.com/wLxzTe3W
You have two errors.
First, the tm passed to mktime is invalid: The year shouldn´t be the absolute year like 2000, but the year difference from 1900, ie. 100 for 2000. With this problem corrected, I get 2004-02-12 as result (neither 2004-02-13 nor 2004-02-10).
(On my computer, the program (without any changes) just crashes: mktime returns -1, localtime can´t handle it and returns an invalid pointer, which is used in the same line...)
Second, in the same struct, the day may be 1-31, but the month only 0-11 (not 1-12). Your 2000-01-02 is the second day of February, not January.
Knowing this, the result is correct (I´ll write the full year, but month starting from 0):
1500 days to add to 2000-01-02:
2000 has 366 days (leap year), and we don´t need January and the first February day:
2000-01-02 + (366-31-1) days = 2001-00-01, 1166 days to add left
Another 365 days makes 2002-00-01, 801 days to add left
Another 365 days makes 2003-00-01, 436 days to add left
Another 365 days makes 2004-00-01, 71 days to add left
Another 31 of January makes 2004-01-01, 40 days to add left
Another 29 of leap February makes 2004-02-01, 11 days to add left
Another 11 added makes 2004-02-12
Read http://www.cplusplus.com/reference/ctime/tm/ carefully
This is the algorithm for adding days to the date.
Calculate day number from date.
function g(y,m,d)
m = (m + 9) % 12
y = y - m/10
return 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + ( d - 1 )
To add no. of days in the date->
g(y2,m2,d2) + no_of_days
After this, you can convert your days back to date.
function d(g)
y = (10000*g + 14780)/3652425
ddd = g - (365*y + y/4 - y/100 + y/400)
if (ddd < 0) then
y = y - 1
ddd = g - (365*y + y/4 - y/100 + y/400)
endif
mi = (100*ddd + 52)/3060
mm = (mi + 2)%12 + 1
y = y + (mi + 2)/12
dd = ddd - (mi*306 + 5)/10 + 1
return y, mm, dd
I keep trying to fead this file into Fortran and output and format the data however I keep getting this message about The Runtime requesting to be terminated or something.
Real X
Real AVG, SUM, Y
open(3, File = 'C: test.txt')
open(5, File = 'C: test1.out')
SUM = 0.
Do 29, J = 1, 30
Read(3, 60) X
60 Format(2x, F4.2)
SUM = SUM + X
29 continue
AVG = Sum / 30
write(5, 65) AVG
65 Format(2x, 'Avg = ', F8.2)
* Read *, Y
Stop
End
Depending on your OS (meaning, compiler and your actual operating system) there are few things that can go wrong with that example.
For a start
open(3, file='c:\test.txt')
is closer how that line is supposed to look like, although it is ususally best to just have the file in the same directory as the working program.
I'm trying to run this MPI Fortran code. There are several problems:
1) when I run this code I expect the program to write 'Enter the number of intervals: (0 quits) ' to screen then ask me n. Instead it asks me n first!!! why?
2) if I don't comment out the line 'goto 10', the program keeps asking me n for ever and does not show me anything else!!!
3) if I comment out 'goto 10' the program ask me n and then writes results. But, problem is every time the program write part of the result not the complete results. It truncate the output!! below are output for three consecutive time I ran the program:
> mpiexec -n 40 ./a.out
10000000
Enter the number of intervals: (0 quits)
pi is 3.14159265358978 Error is 1.287858708565182E-014
time is 1.687502861022949E-002 seconds
> mpiexec -n 40 ./a.out
10000000
Enter the number of intervals: (0 quits)
pi is 3.14159265358978 Error is 1.287858708565182E-014
time is 1.68750286102
> mpiexec -n 40 ./a.out
10000000
Enter the number of intervals: (0 quits)
pi is 3.14159265358978 Error is 1.287858708565182E-014
time is 1.687502861022949E-002 se
Anyone has any idea what's going on? I appreciate your help in advance.
program main
use mpi
double precision starttime, endtime
double precision PI25DT
parameter (PI25DT = 3.141592653589793238462643d0)
double precision mypi, pi, h, sum, x, f, a
double precision starttime, endtime
integer n, myid, numprocs, i, ierr
f(a) = 4.d0 / (1.d0 + a*a) ! function to integrate
call MPI_INIT(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
10 if ( myid .eq. 0 ) then
print *, 'Enter the number of intervals: (0 quits) '
read(*,*) n
endif
starttime = MPI_WTIME()
! broadcast n
call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
! check for quit signal
if ( n .le. 0 ) goto 30
! calculate the interval size
h = 1.0d0/n
sum = 0.0d0
do 20 i = myid+1, n, numprocs
x = h * (dble(i) - 0.5d0)
sum = sum + f(x)
20 continue
mypi = h * sum
! collect all the partial sums
call MPI_REDUCE(mypi,pi,1,MPI_DOUBLE_PRECISION,MPI_SUM,0, &
MPI_COMM_WORLD,ierr)
! node 0 prints the answer.
endtime = MPI_WTIME()
if (myid .eq. 0) then
print *, 'pi is ', pi, 'Error is ', abs(pi - PI25DT)
print *, 'time is ', endtime-starttime, ' seconds'
endif
go to 10
30 call MPI_FINALIZE(ierr)
stop
end
This program is designed to loop via the "goto 10" at the end. The only way to break out of this is for n to have a value <= 0, which will activate the "goto 30" and branch past the "goto 10". Additional clues that this is the intent are the comment "check for quit signal" and that the prompt for the input of n includes "(0 quits)". So try inputting 0!
This is not a good example of modern Fortran. Despite clearly using a Fortran 90 or more recent compiler (the "use" statement shows this), it is written in the style of FORTRAN 77 or earlier. Fixed-source layout, with the source lines apparently starting in column 7. Comment characters in the first column (old Fortran required a C in the first column). "Double Precision". Heavy use of gotos for the program logic. (In my opinion, and others may disagree, there is a place for the goto statement, but not for the basic control flow of a program.) Obsolete Fortran (in my opinion).
The modern Fortran way to express the basic flow:
MainLoop: do
.....
if (n .le. 0) exit MainLoop
....
end do MainLoop
you have to explicitly flush your output. I do not remember if fortran has standard flush function, if flush does not work, try flush_.
Basically what happens, your process zero buffers output, and unless the explicitly tell it to display, you end up a funny stuff