how to calculate years and month from given number c# - c#

I need to calculate years and months from a given number. how can I do it?
eg:
I am giving: 26
I need to get result: 2 years 2months
please help

Unless you have some more specific requirements, it should be as easy as Integer Division and the Remainder operator %
var input = 26;
var years = input / 12;
var months = input % 12;
Console.WriteLine($"{years} years and {months} months");
Output
2 years and 2 months
or
private static (int Years, int Months) GetYearsAndMonths(int input)
=> (input / 12, input % 12);
...
var result = GetYearsAndMonths(26);
Console.WriteLine($"{result.Years} years and {result.Months} months");
or the little known method Math.DivRem Method as supplied by #Charlieface
Calculates the quotient of two numbers and also returns the remainder
in an output parameter.

Related

Problems with formatting decimals in c# [duplicate]

This question already has answers here:
Why does integer division in C# return an integer and not a float?
(8 answers)
Closed 8 months ago.
I'm trying to create a simple C# program (I'm a beginner) to convert days to weeks, months and years. However, the answer always appears in integers, not decimals. For example: 1200 days are equivalent to 3.2876 years, but the program returns only 3. I am using VSCode and .NET 6.0. I tried some output formatting but only got 3.00. Here is the code:
static void Main(string[] args)
{
string aux="";
int daysEntrada=0;
decimal monthSaida, yearsSaida, weeksSaida;
Console.WriteLine("-----------------------------");
Console.WriteLine("days conversor!");
Console.Write("Enter the number of days: ");
Console.WriteLine("\n-----------------------------");
Console.Write("-> ");
aux = Console.ReadLine();
bool isInteiro = int.TryParse(aux, out daysEntrada);
if(isInteiro == true){
daysEntrada = int.Parse(aux);
monthSaida = daysEntrada/30;
yearsSaida = daysEntrada/365;
weeksSaida = daysEntrada/7;
Console.WriteLine($"{daysEntrada} days is equal to: {daysEntrada} days, {weeksSaida} weeks, {monthSaida} months ans {yearsSaida} years.");
}else{
Console.WriteLine("Error, type again.");
}
}
The output generates:
days conversor!
Enter the number of days:
-----------------------------
-> 1200
1200 days is equal to: 1.200,00 days, 171 weeks, 40 months ans 3,00 years
The following is a rule that is valid in C, C++, C# and many more:
Division of two integers gives an integer so when you divide daysEntrada by 365 it returns the floor of the division( for example if it is 3.2876 it returns 3 if it's 3.99 it returns 3).
The solution in C# is to cast any of the values to decimal, I'm no expert in C# but this might work:
yearsSaida = daysEntrada/(decimal)365;
Also an useful article:
How can I divide two integers to get a double?
Try using floats instead of ints and decimals. The original error was caused because your original data type was int so when you divided it it returned an int (non decimal). Here I used floats for all the data types as that way you don't have to cast any values (from int to decimal).
Like this (changes were commented):
public static void Main(string[] args)
{
string aux="";
float daysEntrada=0; // changed from int to float
float monthSaida, yearsSaida, weeksSaida; // changed from decimal to float
Console.WriteLine("-----------------------------");
Console.WriteLine("days conversor!");
Console.Write("Enter the number of days: ");
Console.WriteLine("\n-----------------------------");
Console.Write("-> ");
aux = Console.ReadLine();
bool isInteiro = float.TryParse(aux, out daysEntrada); // changed from int.tryparse to float.tryparse
if(isInteiro == true){
daysEntrada = float.Parse(aux); //changed from int to float
monthSaida = daysEntrada/30;
yearsSaida = daysEntrada/365;
weeksSaida = daysEntrada/7;
Console.WriteLine($"{daysEntrada} days is equal to: {daysEntrada} days, {weeksSaida} weeks, {monthSaida} months ans {yearsSaida} years.");
}else{
Console.WriteLine("Error, type again.");
}
}

Counting groups of people in age ranges

I have a little method to get the number of members in a certain age range. The range is supposed to be inclusive in both ends, i.e. if I call CountSelection(memberList, 16, 19) (where memberList is a List<Member>), I expect to get the number of members aged 16, 17, 18 and 19 summed together:
private int CountSelection(List<Member> members, int minAge, int maxAge)
{
DateTime from = DateTime.Now.AddYears(minAge * -1);
DateTime to = DateTime.Now.AddYears(maxAge * -1);
return members.Count(m =>
m.DateBorn.Date <= from.Date &&
m.DateBorn.Date >= to.Date);
}
However, my method is not reliable - sometimes it will omit members, I'm guessing when birth dates fall between ranges. In the main method, I'm calling CountSelection() several times, each with different ranges, theoretically covering all ages.
What should the query look like to guarantee that all the members will be counted?
I found out why my method was failing. I was just subtracting whole years from the from and to dates, and that resulted in ranges that looked like this (date format dd.mm.yyyy):
0-5 years - 11.04.2014-11.04.2019
6-12 years - 11.04.2007-11.04.2013
13-19 years - 11.04.2000-11.04.2006
20-26 years - 11.04.1993-11.04.1999
... and so on.
Notice the gap of almost a year between each range.
Solution:
Instead of setting the from-date like this:
DateTime from = DateTime.Now.Date.AddYears(-maxAge);
I of course have to subtract a further 1 year and add 1 day:
DateTime from = DateTime.Now.Date.AddYears(-maxAge + 1).AddDays(1);
Now the ranges look like this:
0-5 years - 12.04.2013-11.04.2019
6-12 years - 12.04.2006-11.04.2013
13-19 years - 12.04.1999-11.04.2006
20-26 years - 12.04.1992-11.04.1999
... and so on.
The final, working method looks like this:
private int CountSelection(List<Member> members, int minAge, int maxAge)
{
DateTime from = compareDate.AddYears(-maxAge+1).AddDays(1);
DateTime to = compareDate.AddYears(-minAge);
return members.Count(m =>
m.DateBorn >= from &&
m.DateBorn <= to);
}
It is easier to work with ranges with exclusive upper bounds:
private int CountSelection(List<Member> members, int minAge, int maxAgeExclusive)
{
DateTime from = compareDate.AddYears(-maxAgeExclusive);
DateTime to = compareDate.AddYears(-minAge);
return members.Count(m => m.DateBorn > from && m.DateBorn <= to);
}
Now your ranges will be mathematically more consistent.
0-6 years
6-13 years
13-20 years
20-27 years
etc
Then you can subtract one from the upper limit at the presentation layer.

Add decimal number to Date - C#

How to convert a decimal number (e.g. 2.5) to year and month (2 years and 6 months) and add it to a given date? I tried DateTime.TryParse and it didn't work.
If you are using it for years then multiply the float you have by 12. 2.5 becomes 30months. Then use the addmonths function. If I enter 5 then it will add 60 months which is 5 years
Usually you could just add a TimeSpan or use one of the Add methods, like this:
decimal yearsToAdd = (decimal)2.5;
int years = (int)Math.Floor(yearsToAdd);
decimal months = yearsToAdd - years;
int actualMonths = (int) Math.Floor(months * 12); // or Ceiling or Round
DateTime x = DateTime.Now.AddYears(years).AddMonths(actualMonths);
The problem is, that when you decimal doesn't yield an exacat number of months, how would you know how long e.g. half a month is?
28.0 / 2, 29.0 / 2, 30.0 / 2 or 31.0 / 2?
Would you take the length of the month you started with or one of the possible two months you end up with?
If you init date is dt than
dt = dt.AddMonths((int)(2.5*12));
decimal x =(decimal)2.5;
int nbYear = Convert.ToInt16(x);
var y = x - Math.Truncate(x);
int nbMonth =Convert.ToInt16 (y*12);
// MessageBox .Show (string.Format (" {0} years and {1} months ",nbYear ,nbMonth ));
DateTime dat=DateTime .Now ; // or given date
DateTime dat2 = dat.AddYears(nbYear).AddMonths(nbMonth);
If month is your smallest unit then the solution is, as pointed by many, to multiply number by 12. A more accurate alternative would be to use ticks.
decimal years=3.14592M; // No idea where this came from.
long ticks = (long)(356.0M * (decimal)TimeSpan.TicksPerDay * years);
DateTime futureDate=DateTime.Today.AddTicks(ticks);
Note that solution will not compensate for leap years. It is not difficult to extend it - you need to calculate number of leap years in the period and use average instead of 356.0M to calculate ticks per year (i.e. avg. number of days per year * ticks per day).

Calculate days in years and months?

How to calculate days in years and months in c#?
per example :
If
1. days = 385 then I need to display Year= 1.1 (i.e. 1 year 1 month)
2. days= 234 then I need to display year =0.7 (i.e 0 year 7 months)
How can we calculate in c#?
I did for days=234 /365 and result is coming 0.64 (i.e. 0 year 6 months). But actually it is 7 months.
How to get accurate year and months.
You can do:
double temp = (234.0 /365.0) * 12.0;
int years = (int)temp;
int months = (int)(temp - years);
This is because you were getting 0.64, which is 0.64 years. If you want months, you'd need to multiply that times 12.
In the above, you'll get 0 years and 7 months... That being said, I'm not sure exactly how you want to format this:
string yearsString = string.Format("{0}.{1}", years, months);
Just be aware that this will do 3.11 for 11 months, which is going to be odd, though it was your requirement.
Also, if you want to have this be very general, you might want to use 365.25 instead of 365 to represent a single Julian Year, as it will help you reduce issues due to leap years.
If you don't know the actual dates, then you could estimate:
Number of years: x / 365
Number of months: (x % 365) / 30
where % is modulo
Assuming a month of exactly one-twelfth of a year, and that you want ignore partial months (based on your saying you expect 7 from your example with 7.688 months, then:
int days = 234;
double years = (double)days / 365.242199;
int wholeYears = (int)Math.Floor(years);
double partYears = years - wholeYears;
double approxMonths = partYears * 12;
string horribleFormat = string.Concat(wholeYears, ".", approxMonths);
Are you sure you want this format? The result--at least with the current information provided--will be fuzzy since months are inconsistent lengths.
Consider a couple alternatives:
A Year-only representation, such as 1.25 meaning "1 and one quarter years". This doesn't mix months and years, and as such remains simple since a year is 365 days (except for leap years). It also removes ambiguity such as "does 1.10 == 1.1?"
Using a concrete start date which would allow you to use strongly-type dates. You could easily use a .ToString() with date-formatting arguments to quickly and accurately get your result.
Let do some calculations.
1 mon = 0.1
2 mon = 0.2
.
.
9 mon = 0.9
10 mon = 1.0 [WRONG according to you 1 is a year]
fine then 1 / 12 = 0.083, therefore 0.083 is 1 month
Now,
234 / 365 = 0.64 => 0.64 / 0.083 => 7.7 i.e. 7th month
Therefore fx => days / 365 = ans % 0.083 = result.
I have no time to prove other number but you can try around this formula.
My suggestion would be to use DateTime.AddDays: it will give you all you need. You can also add other time units there:
DateTime f = new DateTime(0);
var y = f.AddDays(361);
Pseudo code
ts= TimeSpan.fromDays(385)
Years = ts.days Modulo 365
months = (ts.days remainder 365) modulo 12
days = (ts.days remainder 365) Remainder 12
answer string years + "." + months + "." + days
In VB
Dim d As DateTime = DateTime.MinValue 'year = 0001
d = d.AddYears(DateTime.Now.Year - 1) 'add current year
d = d.AddDays(234) 'add days
Dim yrs As Integer = d.Year - DateTime.Now.Year 'calculate years
Dim mos As Double = d.Month / 12 'calculate months
Dim answer As Double = yrs + mos
answer = .6666666666
I think that's numerically impossible. What would you do about 1 year and 11 months? 1.11? Because that could mean either 1 year and 1 month and something, or 1 year and 11 months.

Append a digit to an integer and make sure sum of each digits ends with 1

What is the algorithm in c# to do this?
Example 1:
Given n = 972, function will then append 3 to make 9723, because 9 + 7 + 2 + 3 = 21 (ends with 1). Function should return 3.
Example 2:
Given n = 33, function will then append 5 to make 335, because 3 + 3 + 5 = 11 (ends with 1). Function should return 5.
Algorithms are language independent. Asking for "an algorithm in C#" doesn't make much sense.
Asking for the algorithm (as though there is only one) is similarly misguided.
So, let's do this step by step.
First, we note that only the last digit of the result is meaningful. So, we'll sum up our existing digits, and then ignore all but the last one. A good way to do this is to take the sum modulo 10.
So, we have the sum of the existing digits, and we want to add another digit to that, so that the sum of the two ends in 1.
For the vast majority of cases, that will mean sum + newDigit = 11. Rearranging gives newDigit = 11 - sum
We can then take this modulo 10 (again) in order to reduce it to a single digit.
Finally, we multiply the original number by 10, and add our new digit to it.
The algorithm in general:
(10 - (sum of digits mod 10) + 1) mod 10
The answer of the above expression is your needed digit.
sum of digits mod 10 gives you the current remainder, when you subtract this from 10 you get the needed value for a remainder of 0. When you add 1 you get the needed value to get a remainder of 1. The last mod 10 gives you the answer as a 1 digit number.
So in C# something like this:
static int getNewValue(string s)
{
int sum = 0;
foreach (char c in s)
{
sum += Convert.ToInt32(c.ToString());
}
int newDigit = (10 - (sum % 10) + 1) % 10;
return newDigit;
}
Another alternative using mod once only
int sum = 0;
foreach (char c in s)
sum += Convert.ToInt32(c.ToString());
int diff = 0;
while (sum % 10 != 1)
{
sum++;
diff++;
}
if (diff > 0)
s += diff.ToString();
Well, it's easier in C++.
std::string s = boost::lexical_cast<string>( i );
i = i * 10 + 9 - std::accumulate( s.begin(), s.end(), 8 - '0' * s.size() ) % 10;
Addicted to code golf…

Categories