I have to create my own DateTime class with fields seconds,minutes,hours,days,months and years. I've had a problem with realization method void AddDays(int N),which adds N days(N may be negative). I do not understand what idea should lie in this function to add days worked correctly. I was trying to understand how the system class works, but for now it's difficult for me.
public TimeDate(int second, int minute, int hour,
int day, int month, int year)
{
_second = second;
_minute = minute;
_hour = hour;
_day = day;
_month = month;
_year = year;
}
private long _second;
private long _minute;
private long _hour;
private long _day;
private long _month;
private long _year;
private long[] dayYear = {0,31,28,31,30,31,30,31,31,30,31,30,31};
private long[] dayYearLeap ={0,31,29,31,30,31,30,31,31,30,31,30,31};
private bool isLeap()
{
if (_year % 4 == 0)
{
if (_year % 100 == 0)
{
if (_year % 400 == 0)
{
return true;
}
return false;
}
return true;
}
return false;
}
public void AddDays(int N)
{
long N_in_second = N * 60*60*24;
long second_now = _second + _minute * 60 + _hour * 60 * 60 + _day * 60 * 60 * 24;
if (isLeap())
{
second_now += _month*3600*24*dayYearLeap[_month]+
_year * 60 * 60 * 24 * dayYearLeap[_month] * 12;
}
else
{
second_now += _month * 3600 * 24 * dayYear[_month] +
_year * 60 * 60 * 24 * dayYear[_month] * 12;
}
second_now += N_in_second;
_year = second_now / (60*60*24*12*dayYear[_month]);
second_now -= 60 * 60 * 24 * 12 * dayYear[_month];
_month = second_now / (60 * 60 * 24 * dayYear[_month]) % 12;
if (_month == 0) _month = 12;
second_now -= (60 * 60 * 24 * dayYear[_month]);
_day = second_now / (60 * 60 * 24) % dayYear[_month];
second_now -= (60 * 60 * 24);
_hour = second_now / (60 * 60) % 24;
second_now -= (60 * 60);
_minute = second_now / 60 % 60;
second_now -= 60;
_second = second_now % 60;
}
in main function I wrote TimeDate date = new TimeDate(34,27,13,28,2,2019); date.AddDays(5); output was: Second: 34, Minute: 27, Hour: 13, Day: 12, Month: 3,Year: 2019, but it's extra 7 days. Where did I go wrong? if the year becomes a leap year after the summation, how can I catch this?
public void AddDays(int N)
{
if (N >= 0)
{
for (int i = 0; i < N; i++)
{
_day++;
if (isLeap())
{
if (_day > dayYearLeap[_month])
{
_day = 1;
_month++;
if (_month > 12)
{
_year++;
_month = 1;
}
}
}
else
{
if (_day > dayYear[_month])
{
_day = 1;
_month++;
if (_month > 12)
{
_year++;
_month = 1;
}
}
}
}
}
else
{
for (int i = 0; i < Math.Abs(N); i++)
{
_day--;
if (_day == 0)
{
_month--;
if (isLeap())
{
if (_month < 1)
{
_year--;
_month = 12;
}
_day = dayYearLeap[_month];
}
else
{
if (_month < 1)
{
_year--;
_month = 12;
}
_day = dayYear[_month];
}
}
}
}
}
Related
I'm ripping my hair out on the following so I'm kindly asking for help here.
I have an array of durations in minutes whose total is one day (1440 min.)
I have another array with a value which represent a protection level : 0 to 5.
var levels = new int[3];
levels[0] = 0;
levels[1] = 5;
levels[2] = 0;
var minutes = new int[3];
minutes[0] = 658; // 10 hours and 58 minutes
minutes[1] = 1; // 1 minute
minutes[2] = 781; // 13 hours and 1 minutes
In plain English we should read:
Level 0 duration is 10 hours and 58 minutes, then Level 1 duration is 1 minute and finally we're back to level 0 for 13 hours and 1 minute. End of the day ;)
Of couse this is a simple example, this could be more richer than that, but I hope this helps understand the problem I'm trying to solve which is exposed below.
I need to compute an average of protection level for each hour of the day (from 0 to 23)\
The final result set would be an array of tuples with 6 items
var finalResult = new (int level0percent, int level1percent, int level2percent, int level3percent, int level4percent, int level5percent)[24];
With the data in this example that would mean:
100% for level 0 for Hours from 0 to 9
96% for level 0 for Hour 10
A this point we have 2 minutes left (4%) to be given to Hour 10.
We consume 2% (1 minute) for level 5
Still 2% (1 minute) to consume on the next level, which is 0 for now.
We add 2% (1 minute) to level 0
Then the remaining is now 13 hours for level 0 at index 11 to 23.
The tricky part for me is to process, in this case, the hour at index 10. May be I should restructure the data in a form that would be simplier to process, but I can't figure it out.
Any help appreciated.
PS : If Linq could be of any help, please do not hesitate to use it.
EDIT : Fixed the minutes array.
EDIT 2 : This what I've tried so far...
A level class to hold an intermediary result set:
public class Levels
{
public int level0 { get; set; }
public int level1 { get; set; }
public int level2 { get; set; }
public int level3 { get; set; }
public int level4 { get; set; }
public int level5 { get; set; }
}
The processing code so far... May not compile and/or work:
// Construct the final result to be sent back to the client
var averagesOn24HoursByHourNew = Enumerable.Range(0, 24).Select(i => new Levels()).ToArray();
// This index will allow us to advance each hour of the day (from 0 to 23)
int lastIndexOnAveragesOn24HoursByHourNew = 0;
// Used to gather the remaining minutes for incomplete hours
int lastMinuteLeftOnLastHour = 0;
for (var indexLevel = 0; indexLevel < levels.Count; indexLevel++)
{
if (levels[indexLevel] == 0)
{
int durationInMinutes = (int)minutes[indexLevel];
var nbMinutesLeft = durationInMinutes % 60;
var nbHoursAtOneHundred = durationInMinutes / 60;
if (lastMinuteLeftOnLastHour != 0)
{
averagesOn24HoursByHourNew[lastIndexOnAveragesOn24HoursByHourNew].level0 += lastMinuteLeftOnLastHour * 100 / 60;
nbMinutesLeft -= lastMinuteLeftOnLastHour;
lastMinuteLeftOnLastHour = 0;
}
int index = 0;
for (index = lastIndexOnAveragesOn24HoursByHourNew; index < nbHoursAtOneHundred + lastIndexOnAveragesOn24HoursByHourNew; index++)
{
#if DEBUG
Debug.Assert(index <= 23);
#endif
averagesOn24HoursByHourNew[index].level0 += 100;
datiCountForOneHour[index] += 1;
}
#if DEBUG
// When th whole day is processed the index will be 24
Debug.Assert(index < 25);
#endif
if (nbMinutesLeft != 0)
{
averagesOn24HoursByHourNew[index].level0 += nbMinutesLeft * 100 / 60;
if (lastMinuteLeftOnLastHour != 0 && lastMinuteLeftOnLastHour > nbMinutesLeft)
{
lastMinuteLeftOnLastHour -= nbMinutesLeft;
}
else
{
lastMinuteLeftOnLastHour = 60 - nbMinutesLeft;
}
}
lastIndexOnAveragesOn24HoursByHourNew = index;
}
else if (levels[indexLevel] == 1)
{
int durationInMinutes = (int)minutes[indexLevel];
// A duration of zero means less than one minute
// set it to one minute
if (durationInMinutes == 0)
{
durationInMinutes = 1;
}
else if (durationInMinutes == 1439)
{
// FIXME Add Missing minute if needed
durationInMinutes = 1440;
}
var nbMinutesLeft = durationInMinutes % 60;
var nbHoursAtOneHundred = durationInMinutes / 60;
int index = 0;
for (index = lastIndexOnAveragesOn24HoursByHourNew; index < nbHoursAtOneHundred + lastIndexOnAveragesOn24HoursByHourNew; index++)
{
#if DEBUG
Debug.Assert(index <= 23);
#endif
if (lastMinuteLeftOnLastHour != 0)
{
averagesOn24HoursByHourNew[index].level1 += lastMinuteLeftOnLastHour * 100 / 60;
lastMinuteLeftOnLastHour = 0;
}
else
{
averagesOn24HoursByHourNew[index].level1 += 100;
}
datiCountForOneHour[index] += 1;
}
#if DEBUG
// When th whole day is processed the index will be 24
Debug.Assert(index < 25);
#endif
if (nbMinutesLeft != 0)
{
averagesOn24HoursByHourNew[index].level1 += nbMinutesLeft * 100 / 60;
if (lastMinuteLeftOnLastHour != 0 && lastMinuteLeftOnLastHour > nbMinutesLeft)
{
lastMinuteLeftOnLastHour -= nbMinutesLeft;
}
}
lastIndexOnAveragesOn24HoursByHourNew = index;
}
else if (levels[indexLevel] == 2)
{
int durationInMinutes = (int)minutes[indexLevel];
// A duration of zero means less than one minute
// set it to one minute
if (durationInMinutes == 0)
{
durationInMinutes = 1;
}
else if (durationInMinutes == 1439)
{
// FIXME Add Missing minute if needed
durationInMinutes = 1440;
}
var nbMinutesLeft = durationInMinutes % 60;
var nbHoursAtOneHundred = durationInMinutes / 60;
int index = 0;
for (index = lastIndexOnAveragesOn24HoursByHourNew; index < nbHoursAtOneHundred + lastIndexOnAveragesOn24HoursByHourNew; index++)
{
#if DEBUG
Debug.Assert(index <= 23);
#endif
if (lastMinuteLeftOnLastHour != 0)
{
averagesOn24HoursByHourNew[index].level2 += lastMinuteLeftOnLastHour * 100 / 60;
lastMinuteLeftOnLastHour = 0;
}
else
{
averagesOn24HoursByHourNew[index].level2 += 100;
}
datiCountForOneHour[index] += 1;
}
#if DEBUG
// When th whole day is processed the index will be 24
Debug.Assert(index < 25);
#endif
if (nbMinutesLeft != 0)
{
averagesOn24HoursByHourNew[index].level2 += nbMinutesLeft * 100 / 60;
if (lastMinuteLeftOnLastHour != 0 && lastMinuteLeftOnLastHour > nbMinutesLeft)
{
lastMinuteLeftOnLastHour -= nbMinutesLeft;
}
}
lastIndexOnAveragesOn24HoursByHourNew = index;
}
else if (levels[indexLevel] == 3)
{
int durationInMinutes = (int)minutes[indexLevel];
// A duration of zero means less than one minute
// set it to one minute
if (durationInMinutes == 0)
{
durationInMinutes = 1;
}
else if (durationInMinutes == 1439)
{
// FIXME Add Missing minute if needed
durationInMinutes = 1440;
}
var nbMinutesLeft = durationInMinutes % 60;
var nbHoursAtOneHundred = durationInMinutes / 60;
int index = 0;
for (index = lastIndexOnAveragesOn24HoursByHourNew; index < nbHoursAtOneHundred + lastIndexOnAveragesOn24HoursByHourNew; index++)
{
#if DEBUG
Debug.Assert(index <= 23);
#endif
if (lastMinuteLeftOnLastHour != 0)
{
averagesOn24HoursByHourNew[index].level3 += lastMinuteLeftOnLastHour * 100 / 60;
lastMinuteLeftOnLastHour = 0;
}
else
{
averagesOn24HoursByHourNew[index].level3 += 100;
}
datiCountForOneHour[index] += 1;
}
#if DEBUG
// When th whole day is processed the index will be 24
Debug.Assert(index < 25);
#endif
if (nbMinutesLeft != 0)
{
averagesOn24HoursByHourNew[index].level3 += nbMinutesLeft * 100 / 60;
if (lastMinuteLeftOnLastHour != 0 && lastMinuteLeftOnLastHour > nbMinutesLeft)
{
lastMinuteLeftOnLastHour -= nbMinutesLeft;
}
}
lastIndexOnAveragesOn24HoursByHourNew = index;
}
else if (levels[indexLevel] == 4)
{
int durationInMinutes = (int)minutes[indexLevel];
// A duration of zero means less than one minute
// set it to one minute
if (durationInMinutes == 0)
{
durationInMinutes = 1;
}
else if (durationInMinutes == 1439)
{
// FIXME Add Missing minute if needed
durationInMinutes = 1440;
}
var nbMinutesLeft = durationInMinutes % 60;
var nbHoursAtOneHundred = durationInMinutes / 60;
int index = 0;
for (index = lastIndexOnAveragesOn24HoursByHourNew; index < nbHoursAtOneHundred + lastIndexOnAveragesOn24HoursByHourNew; index++)
{
#if DEBUG
Debug.Assert(index <= 23);
#endif
if (lastMinuteLeftOnLastHour != 0)
{
averagesOn24HoursByHourNew[index].level4 += lastMinuteLeftOnLastHour * 100 / 60;
lastMinuteLeftOnLastHour = 0;
}
else
{
averagesOn24HoursByHourNew[index].level4 += 100;
}
datiCountForOneHour[index] += 1;
}
#if DEBUG
// When th whole day is processed the index will be 24
Debug.Assert(index < 25);
#endif
if (nbMinutesLeft != 0)
{
averagesOn24HoursByHourNew[index].level4 += nbMinutesLeft * 100 / 60;
if (lastMinuteLeftOnLastHour != 0 && lastMinuteLeftOnLastHour > nbMinutesLeft)
{
lastMinuteLeftOnLastHour -= nbMinutesLeft;
}
}
lastIndexOnAveragesOn24HoursByHourNew = index;
}
else if (levels[indexLevel] == 5)
{
int durationInMinutes = (int)minutes[indexLevel];
// A duration of zero means less than one minute
// set it to one minute
if (durationInMinutes == 0)
{
durationInMinutes = 1;
}
else if (durationInMinutes == 1439)
{
// FIXME Add Missing minute if needed
durationInMinutes = 1440;
}
var nbMinutesLeft = durationInMinutes % 60;
var nbHoursAtOneHundred = durationInMinutes / 60;
int index = 0;
for (index = lastIndexOnAveragesOn24HoursByHourNew; index < nbHoursAtOneHundred + lastIndexOnAveragesOn24HoursByHourNew; index++)
{
#if DEBUG
Debug.Assert(index <= 23);
#endif
if (lastMinuteLeftOnLastHour != 0)
{
averagesOn24HoursByHourNew[index].level5 += lastMinuteLeftOnLastHour * 100 / 60;
lastMinuteLeftOnLastHour = 0;
}
else
{
averagesOn24HoursByHourNew[index].level5 += 100;
}
datiCountForOneHour[index] += 1;
}
#if DEBUG
// When th whole day is processed the index will be 24
Debug.Assert(index < 25);
#endif
if (nbMinutesLeft != 0)
{
averagesOn24HoursByHourNew[index].level5 += nbMinutesLeft * 100 / 60;
if (lastMinuteLeftOnLastHour != 0 && lastMinuteLeftOnLastHour > nbMinutesLeft)
{
lastMinuteLeftOnLastHour -= nbMinutesLeft;
}
}
lastIndexOnAveragesOn24HoursByHourNew = index;
}
else
{
throw new InvalidOperationException("Invalid protection level found in stats");
}
}
You can try it this way. Probably not the most elegant solution, but gets the job done and can be a basis for further optimization. For explanation see comments in the code.
using System;
using System.Linq;
public class Program
{
class percentages {
public double l0;
public double l1;
public double l2;
public double l3;
public double l4;
public double l5;
public string ToString() {
return $"{l0:F2} {l1:F2} {l2:F2} {l3:F2} {l4:F2} {l5:F2} ";
}
}
public static void Main()
{
var levels = new int[]{0,5,0};
var minutes = new int[]{658, 1, 781};
var plist = new percentages[24];
//sum up the minutes to total duration on this day
//ie minutes will become [658, 659, 1440]
for (int i = 1; i < minutes.Length; i++)
minutes[i] += minutes[i-1];
//lindex is the current index in the levels/minutes array
var lindex = 0;
//pindex is the current index in the percentages array
var pindex = 0;
var p = new percentages();
//a constant of how much 1 minute contributes in percent of an hour
var m1 = 100.0 / 60;
//check every minute of the day
for (int m = 1; m <= 1440; m++) {
//increment the respective level by 1 minute
switch(levels[lindex]) {
case 0: p.l0 += m1; break;
case 1: p.l1 += m1; break;
case 2: p.l2 += m1; break;
case 3: p.l3 += m1; break;
case 4: p.l4 += m1; break;
case 5: p.l5 += m1; break;
}
//if the minutes reached a level change increment the index in the level/minute array
if (m == minutes[lindex]) lindex++;
//if the minutes reached a full hour, add the current percentages to the list, increment index and reset for the next hour
if (m % 60 == 0){
plist[pindex++] = p;
Console.WriteLine(p.ToString());
p = new percentages();
}
}
}
}
Be aware, there are no sanity checks whatsoever. This will break if levels and minutes don't have the same length or if the sum of minutes is not 1440. For further use, you should add these checks.
I suggest you create another array level_at_min where the index is a minute in the day.
level_at_min will be of size 1440 (I show an algorithm to do it later).
In your example you will have
level_at_min[0] = 0
...
level_at_min[657] = 0
level_at_min[658] = 5
level_at_min[659] = 0
...
level_at_min[1439] = 0
If you have that array, you can create an array of lists (of length 60) levels_at_hour,
that will give for your example
levels_at_hour[0] = [0,0, ..., 0]
levels_at_hour[1] = [0,0, ..., 0]
....
levels_at_hour[11] = [0,..., 5,0]
...
levels_at_hour[23] = [0,0,...,0]
With this you can compute the average protection level at each hour, or the percentage of each protection level at each hour, whatever you want.
Algorithm to create level_at_min: (n the length of array levels and array minutes)
minute_counter = 0
for each block in 0 to n-1
for each minute in minute_counter to (minute_counter+minutes[block])
level_at_min[min] = levels[block]
minute_counter = minute_counter + minutes[block]
Algorithm to create levels_at_hour:
for each hour in 0 to 23:
for each minute in i*60 to (i+1)*60
add level_at_min[minute] to the list levels_at_hour[hour]
I'm trying to print the DateTime of the posts but in format like this (Since one hour, Since yesterday, or Since last year), I succeeded to do it using the following code.
But, Is there a better way to do it like this code??
Note: there is a property called Date in this code.
public string GetFormattedDate()
{
var now = DateTime.Now;
var years = now.Year - Date.Year;
// Calculating leap year
if (Date.Date > now.AddYears(-years)) years--;
if (years > 0)
{
return "Since " + ((years > 1) ? $"{years} years" : "last year");
}
var months = now.Month - Date.Month;
if (months > 0)
{
return "Since " + ((months > 1) ? $"{months} months" : "last month");
}
var days = now.Day - Date.Day;
if (days > 0)
{
return "Since " + ((days > 1) ? $"{days} days" : "yesterday");
}
var hours = now.Hour - Date.Hour;
if (hours > 0)
{
return "Since " + ((hours > 1) ? $"{hours} hours" : "one hour");
}
var minutes = Math.Abs(now.Minute - Date.Minute);
if (minutes > 0)
{
return "Since " + ((minutes > 1) ? $"{minutes} minutes" : "one minute");
}
return "Now";
}
This is another Algorithm which is way better than mine.
Thanks to all the contributors in Humanizr and of course to Tieson T.
public static class DateTimeHumanize
{
public static string Humanize(this DateTime input, DateTime comparisonBase)
{
var ts = new TimeSpan(Math.Abs(comparisonBase.Ticks - input.Ticks));
int seconds = ts.Seconds, minutes = ts.Minutes, hours = ts.Hours, days = ts.Days;
int years = 0, months = 0;
// start approximate from smaller units towards bigger ones
if (ts.Milliseconds >= 999)
{
seconds += 1;
}
if (seconds >= 59)
{
minutes += 1;
}
if (minutes >= 59)
{
hours += 1;
}
if (hours >= 23)
{
days += 1;
}
// month calculation
if (days >= 30 & days <= 31)
{
months = 1;
}
if (days > 31 && days < 365)
{
var factor = Convert.ToInt32(Math.Floor((double)days / 30));
var maxMonths = Convert.ToInt32(Math.Ceiling((double)days / 30));
months = (days >= 30 * factor) ? maxMonths : maxMonths - 1;
}
// year calculation
if (days >= 365 && days <= 366)
{
years = 1;
}
if (days > 365)
{
var factor = Convert.ToInt32(Math.Floor((double)days / 365));
var maxMonths = Convert.ToInt32(Math.Ceiling((double)days / 365));
years = (days >= 365 * factor) ? maxMonths : maxMonths - 1;
}
if (years > 0)
{
return "Since " + ((years > 1) ? $"{years} years" : "last year");
}
if (months > 0)
{
return "Since " + ((months > 1) ? $"{months} months" : "last month");
}
if (days > 0)
{
return "Since " + ((days > 1) ? $"{days} days" : "yesterday");
}
if (hours > 0)
{
return "Since " + ((hours > 1) ? $"{hours} hours" : "one hour");
}
if (minutes > 0)
{
return "Since " + ((minutes > 1) ? $"{minutes} minutes" : "one minute");
}
return "Now";
}
public static string RelativeDate(DateTime theDate)
{
Dictionary<long, string> thresholds = new Dictionary<long, string>();
int minute = 60;
int hour = 60 * minute;
int day = 24 * hour;
thresholds.Add(60, "{0} seconds ago");
thresholds.Add(minute * 2, "a minute ago");
thresholds.Add(45 * minute, "{0} minutes ago");
thresholds.Add(120 * minute, "an hour ago");
thresholds.Add(day, "{0} hours ago");
thresholds.Add(day * 2, "yesterday");
thresholds.Add(day * 30, "{0} days ago");
thresholds.Add(day * 365, "{0} months ago");
thresholds.Add(long.MaxValue, "{0} years ago");
long since = (DateTime.Now.Ticks - theDate.Ticks) / 10000000;
foreach (long threshold in thresholds.Keys)
{
if (since < threshold)
{
TimeSpan t = new TimeSpan((DateTime.Now.Ticks - theDate.Ticks));
return string.Format(thresholds[threshold], (t.Days > 365 ? t.Days / 365 : (t.Days > 0 ? t.Days : (t.Hours > 0 ? t.Hours : (t.Minutes > 0 ? t.Minutes : (t.Seconds > 0 ? t.Seconds : 0))))).ToString());
}
}
return "";
}
I want to output a timer in console which goes from 00h00m00s to 23h59m59s.
My code only outputs until 00h00m59s.
Must be the conditions in after the while, but i think it is correct.
Who knows how to solve this ?
static void Main(string[] args)
{
int uur = 0;
int min = 0;
int sec = 0;
while (uur != 23 && min!=60 && sec!=60)
{
if (sec == 60)
{
min++;
sec = 0;
}
if (min == 60)
{
uur++;
min = 0;
}
string strSec = String.Format("{0:00}", sec);
string strMin = String.Format("{0:00}", min);
string strUur = String.Format("{0:00}", uur);
Console.WriteLine(strUur + "h" + strMin + "m" + strSec + "s");
sec++;
}
Console.ReadLine();
}
Use the following condition:
while (uur != 23 || min != 59 || sec != 60)
You might also want to try this simpler approach:
int total_second_in_day = 24*60*60;
for (int second_in_day = 0; second_in_day < total_second_in_day; second_in_day++)
{
int uur = second_in_day / 3600;
int min = (second_in_day % 3600) / 60;
int sec = (second_in_day % 3600) % 60;
string strSec = String.Format("{0:00}", sec);
string strMin = String.Format("{0:00}", min);
string strUur = String.Format("{0:00}", uur);
Console.WriteLine(strUur + "h" + strMin + "m" + strSec + "s");
}
Console.ReadLine();
Although your question is basically about understanding while conditions this is how you could achieve printing all times:
using System;
public class Program
{
public static void Main()
{
var time = new TimeSpan(0,0,0,0);
var oneSec = new TimeSpan(0,0,0,1);
var wakeywakey = new TimeSpan(0,23,59,59);
while (time <= wakeywakey)
{
Console.WriteLine(time);
time += oneSec;
}
}
}
In order to parallelize and accelerate calculations I"ve splitted one long for-cycle by two short for-cycles using TPL, these parts are called PointGenerator and PointGenerator2 in my class bellow:
class CalcPiTPL
{
int n;
int totalCounter;
int counter1;
int counter2;
double aPi;
public StringBuilder Msg; // diagonstic message
Stopwatch stopWatch = new Stopwatch();
public void Init(int aN)
{
stopWatch.Start();
n = aN; // save total calculate-iterations amount
aPi = -1; // flag, if no any calculate-iteration has been completed
Msg = new StringBuilder("No any calculate-iteration has been completed");
}
public void Run()
{
if (n < 1)
{
Msg = new StringBuilder("Invalid N-value");
return;
}
Task[] tasks = new Task[2];
tasks[0] = Task.Factory.StartNew((obj) => { PointGenerator((int)obj); }, n);
tasks[1] = Task.Factory.StartNew((obj) => { PointGenerator2((int)obj); }, n);
Task.WaitAll(tasks[0], tasks[1]);
totalCounter = counter1 + counter2;
aPi = 4.0 * ((double)totalCounter / (double)n); // to calculate approximate Pi - value
Console.WriteLine(aPi);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
}
public double Done()
{
if (aPi > 0)
{
Msg = new StringBuilder("Calculates has been completed successful");
return aPi; // return gotten value
}
else
{
return 0; // no result
}
}
public void PointGenerator(int n)//FIRST PART OF ONE BIG FOR-CYCLE
{
double s = 0.125;
double sP = s / (n / 2);
double x = Math.Sqrt(sP);
for (double cX = 0; cX <= 0.25; cX += x)
{
for (double cY = 0; cY <= 0.5; cY += x)
{
if (((cX - 0.5) * (cX - 0.5) + (cY - 0.5) * (cY - 0.5)) < 0.25)
{
counter1++; // coordinate in a circle! mark it by incrementing N_0
}
}
}
}
public void PointGenerator2(int n)//SECOND PART OF ONE BIG FOR-CYCLE
{
double s = 0.125;
double sP = s / (n / 2);
double x = Math.Sqrt(sP);
for (double cX = 0.25; cX <= 0.5; cX += x)
{
for (double cY = 0; cY <= 0.5; cY += x)
{
if (((cX - 0.5) * (cX - 0.5) + (cY - 0.5) * (cY - 0.5)) < 0.25)
{
counter2++; // coordinate in a circle! mark it by incrementing N_0
}
}
}
}
}
And this is the same class without Tasks using(TPL), it has one long for-cycle:
class TCalcPi//unparallel calculating method
{
int N;
int n_0;
double aPi;
public StringBuilder Msg; // diagnostic message
Stopwatch stopWatch = new Stopwatch();
public void Init(int aN)
{
stopWatch.Start();
N = aN; // save total calculate-iterations amount
aPi = -1; // flag, if no any calculate-iteration has been completed
Msg = new StringBuilder("No any calculate-iteration has been completed");
}
public void Run()
{
if (N < 1)
{
Msg = new StringBuilder("Invalid N - value");
return;
}
double s = 0.25;
double sP = s / N;
double x = Math.Sqrt(sP);
for (double cX = 0; cX <= 0.5; cX += x)//ONE LONG FOR-CYCLE
{
for(double cY = 0; cY <= 0.5; cY += x)
{
if (((cX - 0.5) * (cX - 0.5) + (cY - 0.5) * (cY - 0.5)) < 0.25)
{
n_0++; // coordinate in a circle! mark it by incrementing N_0
}
}
}
aPi = 4.0 * ((double)n_0 / (double)N); // to calculate approximate Pi - value
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
}
public double Done()
{
if (aPi > 0)
{
Msg = new StringBuilder("Calculates has been completed successful");
return aPi; // return gotten value
}
else
{
return 0; // no result
}
}
}
But unparallelized-class works faster, than parallelized(using TPL)class. How to fix it?
counter1 and counter2 most likely sit on the same cache line because they are adjacent in memory. This causes False Sharing. Probably, you are incrementing those counters very often. This pings the cacheline between the L1's of two cores for every alternation in time between the counters.
Separate them. As a proof of concept, like this:
int counter1;
long padding0, p1, p2, p3, p4, p5, p6, p7; //64 bytes padding
int counter2;
Let's hope the JIT does not reorder the fields. Maybe you need to use StructLayout.
Alternatively, make the counters local variables. Stack variables only have false sharing by extreme coincidence.
I have this ListView. My goal is to add / subtract a fixed time to all the times / selected times in the list. The thing is that there will be somewhat around 1000-3000 rows in it, so it takes some time. My goal is to make this as fast for the computer as possible.
Right now if I spam-run the function, it takes some time for the form to finish, and if I chose to do it with selected rows, half of them, then the form freezes for a while before finishing.
My code right now looks like this (here's a picture of the code for better view):
public void PlusMinus(bool plus)
{
int items_to_set = 0;
int msec_start = 0;
int msec_end = 0;
int msec_box = Convert.ToInt32(mskTime.Text.Substring(9, 3)) +
(Convert.ToInt32(mskTime.Text.Substring(6, 2)) * 1000) +
(Convert.ToInt32(mskTime.Text.Substring(3, 2)) * 60000) +
(Convert.ToInt32(mskTime.Text.Substring(0, 2)) * 3600000);
if (rbtnAll.Checked) { items_to_set = listSub.Items.Count; }
else { items_to_set = listSub.SelectedItems.Count; }
if (rbtnAll.Checked)
{
for (int i = 0; i < items_to_set; i++)
{
msec_start = Convert.ToInt32(listSub.Items[i].SubItems[1].Text.Substring(9, 3)) +
(Convert.ToInt32(listSub.Items[i].SubItems[1].Text.Substring(6, 2)) * 1000) +
(Convert.ToInt32(listSub.Items[i].SubItems[1].Text.Substring(3, 2)) * 60000) +
(Convert.ToInt32(listSub.Items[i].SubItems[1].Text.Substring(0, 2)) * 3600000);
msec_end = Convert.ToInt32(listSub.Items[i].SubItems[2].Text.Substring(9, 3)) +
(Convert.ToInt32(listSub.Items[i].SubItems[2].Text.Substring(6, 2)) * 1000) +
(Convert.ToInt32(listSub.Items[i].SubItems[2].Text.Substring(3, 2)) * 60000) +
(Convert.ToInt32(listSub.Items[i].SubItems[2].Text.Substring(0, 2)) * 3600000);
if (plus == true) { msec_start += msec_box; msec_end += msec_box; }
else { msec_start -= msec_box; msec_end -= msec_box; }
TimeSpan ts = TimeSpan.FromMilliseconds(msec_start);
listSub.Items[i].SubItems[1].Text = string.Format("{0:D2}:{1:D2}:{2:D2}:{3:D3}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
ts = TimeSpan.FromMilliseconds(msec_end);
listSub.Items[i].SubItems[2].Text = string.Format("{0:D2}:{1:D2}:{2:D2}:{3:D3}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
}
}
else
{
for (int i = 0; i < items_to_set; i++)
{
msec_start = Convert.ToInt32(listSub.Items[listSub.SelectedIndices[i]].SubItems[1].Text.Substring(9, 3)) +
(Convert.ToInt32(listSub.Items[listSub.SelectedIndices[i]].SubItems[1].Text.Substring(6, 2)) * 1000) +
(Convert.ToInt32(listSub.Items[listSub.SelectedIndices[i]].SubItems[1].Text.Substring(3, 2)) * 60000) +
(Convert.ToInt32(listSub.Items[listSub.SelectedIndices[i]].SubItems[1].Text.Substring(0, 2)) * 3600000);
msec_end = Convert.ToInt32(listSub.Items[listSub.SelectedIndices[i]].SubItems[2].Text.Substring(9, 3)) +
(Convert.ToInt32(listSub.Items[listSub.SelectedIndices[i]].SubItems[2].Text.Substring(6, 2)) * 1000) +
(Convert.ToInt32(listSub.Items[listSub.SelectedIndices[i]].SubItems[2].Text.Substring(3, 2)) * 60000) +
(Convert.ToInt32(listSub.Items[listSub.SelectedIndices[i]].SubItems[2].Text.Substring(0, 2)) * 3600000);
if (plus == true) { msec_start += msec_box; msec_end += msec_box; }
else { msec_start -= msec_box; msec_end -= msec_box; }
TimeSpan ts = TimeSpan.FromMilliseconds(msec_start);
listSub.Items[listSub.SelectedIndices[i]].SubItems[1].Text = string.Format("{0:D2}:{1:D2}:{2:D2}:{3:D3}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
ts = TimeSpan.FromMilliseconds(msec_end);
listSub.Items[listSub.SelectedIndices[i]].SubItems[2].Text = string.Format("{0:D2}:{1:D2}:{2:D2}:{3:D3}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
}
}
}
So is there some changes I could make that would be a somewhat big positive impact on the performance here?
Don't parse the strings at all. Instead, store the data as TimeSpans so there is no parsing at all.
Storing data as strings is bad-practice anyway because it clutters up your code with serialization and deserialization.
Where you store the data is not that important. You can use the object Tag property that is on most WinForms objects or store it elsewhere (maybe in a custom list or dictionary).
Also, your code looks highly redundant. Put common subexpressions into local variables. This will improve code quality and performance.