Math.Round problems - c#

I'm trying to create a clock for my game. My hours and seconds are both float values so I am using Math.Round to round them off to the nearest whole number. The problem is that the Hours and Seconds variables aren't changing at all. Am I using Math.Round wrong?
public void Update()
{
Hours = (float)Math.Round(Hours, 0);
ClockTime = Hours + ":" + Seconds;
if (Hours >= 24)
Hours = 0;
if (Seconds >= 60)
Seconds = 0;
}
In my update method for my day/night class.
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
clock.Hours += (float)elapsed;
clock.Update();
When I print the numbers on the screen, nothing is changing. If I take away the (float) cast to the Math.Round I get an error cannot convert double to float.

Don't use floating point in this case, there's absolutely no reason for an hour, minute or second to be non-integral.
What's almost certainly happening is that you're ending up with a float value like 59.9999 despite the fact you think you're rounding it.
There are real dangers in assuming floating point values have more precision than they actually do.
If you hold your number of seconds in an unsigned integral 32-bit type, you can represent elapsed time from now until about the year 2150 AD, should anyone still be playing your game at that point :-)
Then you simply use integer calculations to work out hours and seconds (assuming you're not interested in minutes as seems to be the case), pseudo-code such as:
hours = elapsed_secs / 3600
secs = elapsed_secs % 3600
print hours ":" seconds
Beyond that advice, what you're doing seems a tad strange. You are adding an elapsed seconds field (which I assume you're checked isn't always set to zero) to the hours variable. That's going to make gameplay a little difficult as time speeds by at three and a half thousand times its normal rate.

Actually, you should used DateTime to track your time and use the DateTime properties to get the hours and seconds correctly instead trying it yourself using float for seconds and hours. DateTime is long based and supports from fractions of milliseconds to millenias and of course seconds. It has all the functions built in to add milliseconds or years or seconds or ... correctly, which is actually rather difficult.

Related

C# int for hours and minutes, custom AddMinute Method

I have a custom time model with an Integer for hours and an Integer for minutes, seconds.
The class has an AddMinute(int value) method and I want that e.g....
CustomTime myTime = new CustomTime();
myTime.AddMinute(75);
...the minutes are added as Hours += 1 and Minutes += 15.
I have the solution myself, but am currently looking for the shortest possible one that does this
Does anyone know a good one?
For your current class the best answer I think is what René Vogt mentioned in the comments:
Hours += (value + Minutes) / 60;
Minutes = (value + Minutes) % 60;
However I don't see a point in reinventing the wheel, You can use TimeSpan struct instead of your own CustomTime class, which already have all these options, and not only adding seconds, minutes, ... you can add/subtract another time and more:
TimeSpan Struct (Microsoft Docs)

How to identify date is in seconds or minutes in c#

I have a integer number say Int64 i. the data in this variable is both in minute format and seconds format. Ho can identify the integer number is in munutes or in seconds
suppose,
Int64 i = 0;
now values may be..(For date 2016-02-18 00:00:00:000)
i = 1140220800; //(value is in seconds)
//or
i = 19003680; //(value is in minutes i.e. 1140220800/60)
No how to identify data is in minutes or seconds ?
Well you could just assume that if the number if smaller than some threshold value which makes sense in your context then it's minutes, else it's seconds. For example:
int number = 19003680;
if(number < 42076800) // 2050-01-01 in minutes, 1971-03-05 in seconds.
{
// minutes
}
else
{
// seconds
}
However, this question goes against the principles of good programming - one variable should only have one meaning. If a variable can represent both seconds and minutes, there's a problem in the design of your data.
EDIT:
If you can't reasonably fence your data to where seconds and minutes don't overlap - that is, if you can have both large dates represented in seconds, and small dates represented in minutes, then sadly it's impossible to differentiate between the two.

How time consuming is TImeSpan arithmetic compared to normal arithmetic?

I have a C# program with an interrupt that processes part of a list I'd like to have run as often as every 40 ms, but the math inside the interrupt can freeze up the program for lists with certain sizes and properties.
I'm tempted to try speeding it by removing the TimeSpan adds and subtracts from the math and converting them all to TotalMilliseconds before performing the arithmetic rather than after. Does anyone know what the overhead is on adding and subtracting TimeSpans compared to geting the TotalMilliseconds and adding and subtracting that?
Thanks.
That would be unwise, Timespan.TotalMilliseconds is a property of type double with a unit of one millisecond. Which is highly unrelated to the underlying structure value, Ticks is a property getter for the underlying field of type long with a unit of 100 nanoseconds. The TotalMilliseconds property getter goes through some gymnastics to convert the long to a double, it makes sure that converting back and forth produces the same number.
Which is a problem for TimeSpan, it can cover 10,000 years with a precision of 100 nanoseconds. A double however has 15 significant digits, that's not enough to cover that many years with that kind of precision. The TotalMilliseconds property performs rounding, not just conversion, it makes sure the returned value is accurate to one millisecond. Not 100 nanoseconds. So converting it back and forth always produces the same value.
Which does work: 10,000 years x 365.4 days x 24 hours x 60 minutes x 60 seconds x 1000 milliseconds = 315,705,600,000,000 milliseconds. Count the digits, exactly 15 so exactly good enough to store in a double without loss of accuracy. Happy coincidence, isn't it?
Answering the question: if you care about speed then always use Ticks, never TotalMilliseconds. That's a very fast 64-bit integer operation. Way faster than an integer-to-float + rounding conversion.

Coverting INT to decimal following mm.ss format

I may be being really stupid here, but my brain's gone blank.
I've got a slider bar (which uses Int32 values) but I want to use it to select a position in a music song (mm.ss)
I also want to output the value that the slider is displaying in to a label above it, so it's easier to see what the slider is set to.
Anyone have any suggestions?
I thought of trying to convert the int value in to a decimal then dividing by 60.
I'm doing this in C# by the way.
What does the int value represent? If it's the number of seconds through the song, you should use:
TimeSpan time = TimeSpan.FromSeconds(seconds);
string text = time.ToString(#"mm\.ss");
Using a decimal would be a really bad idea - a format with a number of seconds isn't the same as a fractional number of minutes. For example, 10.50 minutes as a fractional number of minutes is 10 minutes and 30 seconds, not 10 minutes and 50 seconds, which is what you want as far as I can tell.
TimeSpan is the natural way of representing a time duration in .NET... which is why that's the type which supports formatting in minutes and seconds.
Converting it into decimal would not display it the way that you want it. For example four and an half minute would display as 4:50, not 4:30.
Divide the time into minutes and seconds, and format them:
int minutes = time / 60;
int seconds = time % 60;
string formatted = minutes.ToString() + ":" + seconds.ToString("00");
You should represent the length of the song internally as seconds (which can be saved in an int). To actually display it, you do song_length / 60 to get the minutes (this is called integer division, it returns the result and discards the fraction, e.g. 100/60 = 1).
After that, you can get the seconds by song_length % 60 (% is the modulo operator).
Edit: didn't see the c# tag. Jon Skeet's answer is more appropiate in c#.
Edit: I misunderstood the scope of the question, but I'll leave this in case it's helpful.
Store the total length of the track in seconds.
Calculate the position of the slider as a fraction of the maximum possible slider value.
Multiply the track length (in seconds) with fractional value obtained in 2). This gives the offset from the start of the track in seconds.
Format the value from 3) for display.
Here is a contrived example to illustrate the process:
int maxSliderValue = 100;
int sliderValue = 18;
int trackLengthInSeconds = 248;
float sliderFraction = ((float)sliderValue)/((float)maxSliderValue);
int offsetInSeconds = Convert.ToInt32(Math.Floor(trackLengthInSeconds * sliderFraction));
TimeSpan offset = TimeSpan.FromSeconds(offsetInSeconds);
string displayValue = offset.ToString(#"mm\.ss");

DateTime, minutes since update?

I have this DateTime object (update) which is set to DateTime.now, when i update my application.
I also have this timerTick event, called on every 5 seconds which should check how many minutes ago, update was.
I've tried with:
if ((DateTime.Now - Updated).Minutes > 0)
{
updateTextBlock.Text = "updated " + ((DateTime.Now - Updated).Minutes).ToString() + " minutes ago";
}
But it does not seem to work correctly. Isn't there a better way to do this?
/R
I suspect you want TotalMinutes instead of Minutes. Otherwise you'll only ever get a value in the range -59 to 59.
You may also want to consider using UtcNow instead of Now - otherwise you could get odd effects due to time zone changes (either the user changing time zone, or the time zone changing its UTC offset, usually for daylight saving time.)
You may find it easier to use an instance of System.Diagnostics.StopWatch to keep track of how much time has elapsed since any particular starting point.
It can be more reliable and accurate than doing math on DateTime objects because it'll use the hardware's High Resolution Timer if one is available.
You're probably looking for TotalMinutes, not just Minutes. TotalMinutes will give you the total number of minutes in the interval, whereas Minutes only gives 0-59 (since you also have Hours, etc.)
One way I did something similar was using TimeSpan
I had two variables timePassed and tickTime
where I would set tickTime to be a 5 second TimeSpan and timePassed to be 0
TimeSpan tickTime = new TimeSpan(0,0,0,5); // 5 seconds
TimeSpan timePassed = new TimeSpan(0,0,0,0); // 0 seconds
then in the handler for the tick event I would add tickTime to timePassed
timePassed = timePassed.Add(tickTime); \\ adds 5 seconds to the timePassed TimeSpan
Then you can use timePassed to get the time since update.
Hope this helps

Categories