This question already has answers here:
C# Short Error: Negating the minimum value of a twos complement number is invalid
(4 answers)
Closed 9 years ago.
I get a strange error on this little snippet:
private int CalculateDifference(DateTime date1, DateTime date2)
{
var difference = date1 - date2;
return Math.Abs((int)difference.TotalSeconds);
}
In my case I'm calculating a difference of 3520789176.4909997 total seconds. The program throws an exception I´ve never seen in ten years of C# coding:
System.OverflowException: "Negating the minimum value of a twos complement number is invalid."
I´m pretty sure it´s related to floating point arithmetics, but I don´t understand the details and I just need a sufficient solution to determine the difference of the two date values.
The problem is that the when the a double exceeds the range of values that can be expressed in an int—which is -2,147,483,648 to 2,147,483,647, the result is undefined according to the C# specification (See Jeppe Stig Nielsen's comment below), but in the .NET implementation, is int.MinValue. So when you convert difference to an int, it takes the value, -2,147,483,648 which then cannot be negated using Math.Abs
If you convert this method to use long instead, it should work:
private long CalculateDifference(DateTime date1, DateTime date2)
{
var difference = date1 - date2;
return Math.Abs((long)difference.TotalSeconds);
}
You could also solve this by simply converting to int after you've taken the absolute value:
private int CalculateDifference(DateTime date1, DateTime date2)
{
var difference = date1 - date2;
return (int)Math.Abs(difference.TotalSeconds);
}
According to msdn: value of Int.Maxvalue is 2,147,483,647
Your number seems to be greater than that.
Related
This question already has answers here:
Why are floating point numbers inaccurate?
(5 answers)
Closed 4 months ago.
static void Main()
{
var result1 = Converter.ConvertToInt32("922336666");
//result1 one return as 922336666
var result2 = Converter.ConvertToInt64("92233720368547758");
//result2 one return as 92233720368547760
}
}
public static class Converter {
public static int ConvertToInt32(string input) {
return Convert.ToInt32(Math.Round(Convert.ToDouble(input)));
}
public static Int64 ConvertToInt64(string input)
{
return Convert.ToInt64(Math.Round(Convert.ToDouble(input)));
}
}
I am getting result2 rounded up to 92233720368547760 but result1 is kept the same. Can some one explain. When using ToDouble does round up the int ?
The documentation of System.Double Struct (double in C#) says:
A Double value has up to 15 decimal digits of precision
Where about 17 digits are stored but the extra digits are not guaranteed to be precise. Note that the number is effectively stored in a binary format, so the number of decimal digits is only an approximation.
Your second number has 17 digits. This explains why the conversion was not accurate.
Use a System.Decimal Struct (decimal in C#) instead. According to Floating-point numeric types (C# reference) it has a precision of 28-29 digits.
I'm working on a project which calculates a cost of calls from two different times entered by the user. I've parsed the data into the code as DateTime.
DateTime starttime = new DateTime(Convert.ToDateTime(cal1.SelectedDate).Year,Convert.ToDateTime(cal1.SelectedDate).Month,Convert.ToDateTime(cal1.SelectedDate).Day,
Convert.ToInt32(drpdwn1.SelectedValue),
Convert.ToInt32(drpdwn2.SelectedValue),
Convert.ToInt32(drpdwn3.SelectedValue));
DateTime endtime = new DateTime(Convert.ToDateTime(cal1.SelectedDate).Year, Convert.ToDateTime(cal1.SelectedDate).Month, Convert.ToDateTime(cal1.SelectedDate).Day,
Convert.ToInt32(drpdwn4.SelectedValue),
Convert.ToInt32(drpdwn5.SelectedValue),
Convert.ToInt32(drpdwn6.SelectedValue));
And subtracts the two to get a timespan.
TimeSpan duration3 = (endtime - starttime);
txtDisplay.Text = duration3.ToString();
Can someone help me find a way to multiply $0.35 to the timespan duration3?
Here is what I'm using right now but the textbox keeps displaying 0
double mins = duration3.Minutes;
double hrs = duration3.Hours;
double cost = ((hrs * 60) + mins) * 0.35;
txtCost.Text = cost.ToString();
//$0.35/min
// ((0.35*60)*hr + 0.35*min)
Possibly something like:
static decimal Foo(TimeSpan duration, decimal perMinuteRate)
=> ((decimal)duration.TotalMinutes) * perMinuteRate;
although note that TotalMinutes is a double, so this could have unexpected rounding if your duration is very fractional.
Better to do it this way, so you don't interfer with double precision errors:
public static decimal MultiplyPerMinute(TimeSpan a, decimal b)
{
return a.Ticks * b / TimeSpan.TicksPerMinute;
}
When you work with decimal, only double or float should scare you off in any possible operator. Decimal is a type made specificaly for digital, and precision durable operations.
As written, the question is not very clear. There are two questions really:
How to multiply a TimeSpan by a decimal?
Why is my TextBox always displaying zero?
Question 1 is not clear - it can be interpreted in many ways. From reading the posted code, comments and other answers it is possible to see that you are trying to calculate the "cost of a TimeSpan given the cost per minute". Why not ask this question?
But that isn't really your question - your posted code does indicate that you have an idea about how to calculate the "cost of a TimeSpan given the cost per minute", the problem is that your "textbox keeps displaying 0".
From the code posted, I don't know why this is. However, following some good debugging practices should fairly quickly help you narrow down the problem yourself.
See this link to a post by Eric Lippert that you should find useful:
How to debug small programs
No need to calculate the minutes yourself - and multiplying is easy:
TimeSpan ts = DateTime.Now - DateTime.Today;
var cost = ((int)ts.TotalMinutes) * 0.35m; // cost per minute, edited wrongly used 0.63m
I am int ing out the decimals of TotalMinutes to avoid billing for 23.2832s as well ;)
This question already has answers here:
Converting a double to an int in C#
(5 answers)
Closed 6 years ago.
I can't understand the difference between Convert.ToInt32 and Parsing (int) command when i convert a double number to a int number.My example code is here and i have two different answer when i show it.
class Program
{
static void Main(string[] args)
{
double i = 3.897456465;
int y;
y = Convert.ToInt32(i);
Console.WriteLine(y);
y = (int)i;
Console.WriteLine(y);
Console.ReadKey();
}
}
(int) i; is casting not parsing.
Convert.ToInt32(double) would round the number to nearest 32 bit integer. Whereas casting (int) i; would only take the integer part of the double value and assign it to the variable.
Since one does rounding and the other just take the integer value, you see the difference.
Consider the following example:
double d = 1.99d;
int castedValue = (int) d; //1
int convertedValue = Convert.ToInt32(d); //2
In the above code, casting returned 1 since that is the integer part of the double value, whereas the conversion using Convert.ToInt32 rounded the value.
From the documentation from Convert.ToInt32(double):
Return Value
Type: System.Int32
value, rounded to the nearest 32-bit signed integer. If value is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.
From the C# 5 specification section 6.2.1, explicit numeric conversions:
For a conversion from float or double to an integral type [...]
[...]
Otherwise, the source operand is rounded towards zero to the nearest integral value. If this integral value is within the range of the destination type then this value is the result of the conversion.
(Emphasis mine.)
So basically, Convert.ToInt32 rounds up or down to the nearest int. Casting always rounds towards zero.
This question already has answers here:
Date difference in years using C# [duplicate]
(18 answers)
Closed 8 years ago.
I need to output the difference between 2 days in years, months and days.
With timespan and subtract i only get the days but is it possible to output in years, months and days.
This is what i have so far:
public string Leeftijdsverschil(DateTime p1, DateTime p2)
{
if (p1 > p2)
{
DateTime verschil = p1.Subtract(TimeSpan.FromTicks(p2.Ticks));
return verschil.ToString();
}
else
{
DateTime verschil = p2.Subtract(TimeSpan.FromTicks(p1.Ticks));
return verschil.ToString();
}
}
The .NET types don't give you a decent answer to this without having to write code to try one answer and adjust appropriately, but my Noda Time project is designed to handle this sort of thing. For example:
LocalDate x = new LocalDate(2013, 5, 21);
LocalDate y = new LocalDate(2014, 12, 15);
Period p = Period.Between(x, y);
Console.WriteLine("{0} {1} {2}", p.Years, p.Months, p.Days);
Result:
1 6 24
(i.e. 1 year, 6 months and 24 days)
If you decide to use Noda Time for this, you could just do it within your method, using DateTime elsewhere and converting between the types... but it would generally be better to embrace Noda Time more widely. The aim is for it to allow your code to be clearer than just using DateTime.
To get the delta, just subtract directly:
var delta = p1 - p2;
This gives you a TimeSpan. From there, you have access to .Days. Months and years, however, are much more complicated. If you want the difference in those terms, you'll have to compare the properties of p1 and p2 directly (or: as Jon says: use Noda Time)
This question already has answers here:
What is the best way to divide two TimeSpan objects?
(4 answers)
Closed 5 years ago.
I have a value in TimeSpan, let's say: tsp1 = 2 hour 5 minutes.
I have another TimeSpan variable which contains a value like: tsp2 = 0 hours 2 minutes
Please tell me how I can divide tsp1 by tsp2 so that I can get the exact number of times tsp2 divides into tsp1 and what the remainder is.
I am using Visual Studio 2008.
Thanks.
The simplest approach is probably just to take their lengths in ticks, and divide those. For example:
long ticks1 = tsp1.Ticks;
long ticks2 = tsp2.Ticks;
long remainder;
long count = Math.DivRem(ticks1, ticks2, out remainder);
TimeSpan remainderSpan = TimeSpan.FromTicks(remainder);
Console.WriteLine("tsp1/tsp2 = {0}, remainder {1}", count, remainderSpan);
a div b:
double adivb = (double)a.Ticks/b.Ticks;
edited:
i found another post on th same topic
How can I achieve a modulus operation with System.TimeSpan values, without looping?
An int will hold enough seconds for ~64 years, so as long as you stay well below that:
int count = (int) (tsp1.t.TotalSeconds / tsp2.t.TotalSeconds);
double remainder = tsp1.t.TotalSeconds - (count * tsp2.t.TotalSeconds);
And maybe convert the remainder to int as well.