I have some issue when calculating 3 CGFloats
I have: -34.522 + 39.049 + 0.2889 = ios gives me 73
but it should give me more like aproximative to an normal calculator values like = 4.81
CGFloat x = (46.2076 * -34.522) + (60.3827 * 39.049) + (2.028 * 0.2889);
NSLog(#"d %f",x); ->> 763.291199
CGFloat t = -34.522 + 39.049 + 0.2889;
NSLog(#"%f",t);
I'm not 100% sure if this is what you're asking, but if you only want 2 digits of precision, you have to specify this. It's easy to do via format specifier by using %.2f where 2 is the number of digits after the decimal place to be shown.
CGFloat x = (46.2076 * -34.522) + (60.3827 * 39.049) + (2.028 * 0.2889);
NSLog(#"d %.2f",x);
Alternatively, this can also be done with NSNumberFormatter.
NSNumberFormatter *formatter = [NSNumberFormatter new];
[formatter setPositiveFormat:#"#.##"];
NSString *output = [formatter stringFromNumber:#(x)];
NSLog(#"Out: %#",output);
Related
This is the follow up of a previous question of mine.
In a nutshell, I am trying to follow this tutorial step-by-step: https://jtauber.github.io/mars-clock/ to get to Coordinated Mars Time, but I got stuck right before the end. My code works fine up until the end (some values are more accurate than in the tutorial because I went back to the source from NASA: https://www.giss.nasa.gov/tools/mars24/help/algorithm.html ):
double millis = ( [[NSDate date] timeIntervalSince1970] * 1000 );
NSLog(#"millis: %f", millis);
double JDUT = ( 2440587.5 + (millis / 86400000) );
NSLog(#"JDUT: %f", JDUT);
double JDTT = ( JDUT + (37 +32.184) / 86400);
NSLog(#"JDTT: %f", JDTT);
double J2000Epoch = ( JDTT - 2451545.0 );
NSLog(#"J2000Epoch: %f", J2000Epoch);
double MSD = ( (( J2000Epoch - 4.5 ) / 1.0274912517) + 44796.0 - 0.0009626 );
NSLog(#"MSD: %f", MSD);
The only step remaining is actually calculating Coordinated Mars Time, using this equation:
MTC = mod24 { 24 h × MSD }
The problem is that I have no idea how. I tried to use modf( (double), (double *) ) but no idea how it actually works. I tried it the way below, but it gave me an incorrect answer (obviously as I have really no idea what I am doing). :(
double MSD24 = (24 * MSD);
double MCT = modf(24, &MSD24);
NSLog(#"MCT: %f", MCT); // Result: 0.000000
Any help would be much appreciated. Thank you very much!
p.s.: Notice that I use Objective-C; I do not understand swift unfortunately! :(
Carrying on from the code you gave, I tried:
CGFloat MTC = fmod(24 * MSD, 24);
and got
// 19.798515
which was right according to the web page you cited at the moment I tried it.
The sort of thing his page actually shows, e.g. "19:49:38" or whatever (at the time I tried it), is merely a string representation of that number, treating it as a number of hours and just dividing it up into minutes and seconds in the usual way. Which, I suppose, brings us to the second part of your question, i.e. how to convert a number of hours into an hours-minutes-seconds representation? But that is a simple matter, dealt with many times here. See NSNumber of seconds to Hours, minutes, seconds for example.
So, carrying on once again, I tried this:
CGFloat secs = MTC*3600;
NSDate* d = [NSDate dateWithTimeIntervalSince1970:secs];
NSDateFormatter* df = [NSDateFormatter new];
df.dateFormat = #"HH:mm:ss";
df.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSString* result = [df stringFromDate:d];
NSLog(#"%#", result); // 20:10:20
...which is exactly the same as his web page was showing at that moment.
And here's a Swift version for those who would like to know what the "mean time" is on Mars right now:
let millis = Date().timeIntervalSince1970 * 1000
let JDUT = 2440587.5 + (millis / 86400000)
let JDTT = JDUT + (37 + 32.184) / 86400
let J2000Epoch = ( JDTT - 2451545 )
let MSD = (( J2000Epoch - 4.5 ) / 1.0274912517) + 44796.0 - 0.0009626
let MTC = (24 * MSD).truncatingRemainder(dividingBy: 24)
let d = Date(timeIntervalSince1970: MTC*3600)
let df = DateFormatter()
df.dateFormat = "HH:mm:ss"
df.timeZone = TimeZone(abbreviation: "GMT")!
df.string(from:d)
I have the following variable:
NSNumber *consumption = [dict objectForKey:#"con"];
Which returns 42. How can I pad this number to 10 digits on the left, leading with zeros. The output should look as,
0000000042
or if it were 420,
0000000420
NSString *paddedStr = [NSString stringWithFormat:#"%010d", 42];
EDIT: It's C style formatting. %nd means the width is at least n. So if the integer is 2 digit long, then you will have length 3 string (when %3d is used). By default the left empty spaces are filled by space. %0nd (0 between % and n) means 0 is used for padding instead of space. Here n is the total length. If the integer is less than n digits then left padding is used.
The Objective-C way,
NSNumberFormatter * numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
[numberFormatter setPaddingPosition:NSNumberFormatterPadBeforePrefix];
[numberFormatter setPaddingCharacter:#"0"];
[numberFormatter setMinimumIntegerDigits:10];
NSNumber * number = [NSNumber numberWithInt:42];
NSString * theString = [numberFormatter stringFromNumber:number];
NSLog(#"%#", theString);
The C way is faster though.
You can't in the NSNumber itself. If you're creating a string from the number or using NSLog(), simply use the appropriate format, e.g.
NSLog(#"%010d", [consumption intValue]);
You can do pretty much any number formatting you would ever want with NSNumberFormatter. In this case I think you would want to use the setFormatWidth: and setPaddingCharacter: functions.
with variable num_digits
NSString* format =[NSString stringWithFormat:#"%%0%zdzd", num_digits];
NSString *theString = [NSString stringWithFormat:format, 42];
E.g. Fill the rest with zeros, 5 digits:
NSInteger someValue = 10;
[NSString stringWithFormat:#"%05ld", someValue];
Equivalent of .02f for float number when you need only 2 digits after the dot.
So there you have 0 = fill with zeros, 5 = the number of digits and type.
Solution for Swift 3
let x = 1078.1243
let numFormatter = NumberFormatter()
numFormatter.minimumFractionDigits = 1 // for float
numFormatter.maximumFractionDigits = 1 // for float
numFormatter.minimumIntegerDigits = 10 // how many digits do want before decimal
numFormatter.paddingPosition = .beforePrefix
numFormatter.paddingCharacter = "0"
let s = numFormatter.string(from: NSNumber(floatLiteral: x))!
OUTPUT
"0000001078.1"
Not sure how to word the title correctly... but what I am wondering is if there is some clever format specifier that will take the number 4.5 and give me #"4.5" but also take the number 2 and give me #"2".
Using the %.1f specifier gives me #"4.5" but also #"2.0". I am trying to get rid of the ".0" bit.
Does such a beast exist, or am I going to have to do some math on this? FWIW, I am trying to iterate over an array of values ranging from 0 to 5 increasing in half-steps, so 0, 0.5, 1, 1.5, ..., 4.5, 5
Cheers!
NSNumberFormatter is a good choice here. You can configure it to not show the fractional digits if the number is an integer. For example:
NSArray *numbers = #[#0, #0.5, #1.0, #1.5, #2.0, #2.5];
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.alwaysShowsDecimalSeparator = NO;
numberFormatter.minimumFractionDigits = 0;
numberFormatter.maximumFractionDigits = 1;
numberFormatter.minimumIntegerDigits = 1;
for (NSNumber *number in numbers) {
NSLog(#"%#", [numberFormatter stringFromNumber:number]);
}
Output:
>> 0
>> 0.5
>> 1
>> 1.5
>> 2
>> 2.5
This is even easier (Swift):
let num1: Double = 5
let num2: Double = 5.52
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .DecimalStyle
print(numberFormatter.stringFromNumber(NSNumber(double: num1)))
print(numberFormatter.stringFromNumber(NSNumber(double: num2)))
This will print 5 and then 5.52.
I am trying to make an approximation of the length of day from sunrise to sunset, and the length of night from sunset to sunrise. My present approximation is crude (it assumes yesterday and tomorrow have equivalent values to today), but for now I am not specifically concerned with pinpointing yesterday sunset, today sunrise, today sunset, and tomorrow sunrise (yet). My goal is a calculation based on twelve equal hours per night (twelve equal to each other, not equal to a standard hour or daytime hour), and twelve equal hours per day.
What I am concerned with is that in my iOS app, the calculation is way off; a minute flies by in 5-6 (standard) seconds' time. When I use unmodified time, in other code from here, the clock moves at a standard pace, but when I try to get this code to feed the clock code, something is out of bounds.
The code I've been working on, as an approximation, is:
NSDate *now = [[NSDate alloc] init];
NSDate *factory = [[NSDate alloc] init];
NSDate *summerSolstice2013 = [factory initWithTimeIntervalSinceReferenceDate:_referenceSummerSolstice];
double distanceAlong = [now timeIntervalSinceDate:summerSolstice2013];
double angleAlong = M_PI * 2 * distanceAlong / (2 * (_referenceWinterSolstice - _referenceSummerSolstice));
double currentHeight = cos(angleAlong) * _latitudeAngle + _tiltAngle;
...
if (_secondsAreNatural)
{
_secondsAreShadowed = FALSE;
double dayDuration = 12 * 60 * 60 + 12 * 60 * 60 * sin(currentHeight);
double midday = fmod(24 * 60 * 60 * _longitudeAngle / (2 * M_PI) + 12 * 60 * 60, 24 * 60 * 60);
double sunrise = midday - dayDuration / 2;
double sunset = midday + dayDuration / 2;
double seconds = fmod([now timeIntervalSinceReferenceDate], 24 * 60 * 60);
double proportionAlong = 0;
if (seconds < sunrise)
{
_naturalSeconds = (seconds - sunset - 24 * 60 * 60) / (sunrise - sunset - 24 * 60 * 60);
}
else if (seconds > sunset)
{
_naturalSeconds = 12 * 60 * 60 * (seconds - sunset) / (sunrise + 24 * 60 * 60 - sunset) + 18 * 60 * 60;
}
else
{
_naturalSeconds = 12 * 60 * 60 * (seconds - sunrise) / (sunset - sunrise) + 6 * 60 * 60;
}
}
Are there any problems (given that this approximation can probably be refined to any extent) you can pinpoint in this code?
Thanks,
--EDIT--
The code I wrote above was fairly demanding in terms of the loose ends presented to someone reading it. I tried to take another pass, and rewrite it in simpler terms and with a purer mathematical model. I wrote, comments added:
NSDate *now = [[NSDate alloc] init];
NSDate *summerSolstice2013 = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:_referenceSummerSolstice];
double distanceAlong = [now timeIntervalSinceDate:summerSolstice2013];
// How far along are we, in seconds, since the reference date?
double angleAlong = M_PI * 2 * distanceAlong / (2 * (_referenceWinterSolstice - _referenceSummerSolstice));
// What's the angle if 2 π radians corresponds to a whole year?
double currentHeight = cos(angleAlong) * _latitudeAngle + _tiltAngle;
// _latitudeAngle is the angle represented by our latitude; _tiltAngle is the angle of the earth's tilt.
NSInteger day = 24 * 60 * 60;
// 'day' could have been called secondsInADay, but it was mean to reduce the number of multiplicands represented in the code.
// If we are in the endless day or endless night around the poles, leave the user with standard clock hours.
if (currentHeight > M_PI / 2)
{
_secondsAreShadowed = TRUE;
}
else if (currentHeight < - M_PI / 2)
{
_secondsAreShadowed = TRUE;
}
// Otherwise, calculate the time this routine is meant to calculate. (This is the main intended use case.)
else if (_secondsAreNatural)
{
_secondsAreShadowed = FALSE;
// closestDay is intended to be the nearest midnight (or, in another hemisphere, midday), not exactly in hours offset from UTC, but in longitude offset from Greenwich.
double closestDay;
if (fmod(distanceAlong, day) < .5 * day)
{
closestDay = distanceAlong - fmod(distanceAlong, day);
}
else
{
closestDay = day + distanceAlong - fmod(distanceAlong, day);
}
// As we go through the calculations, for the most part we keep up information on the previous and next days, which will to some degree be consulted at the end.
double previousDay = closestDay - day;
double nextDay = closestDay + day;
// For the three days, what proportion of the way along are they from the solstices?
double closestDayAngleAlong = M_PI * 2 * closestDay / (2 * (_referenceWinterSolstice - _referenceSummerSolstice));
double previousDayAngleAlong = M_PI * 2 * previousDay / (2 * (_referenceWinterSolstice - _referenceSummerSolstice));
double nextDayAngleAlong = M_PI * 2 * nextDay / (2 * (_referenceSummerSolstice - _referenceSummerSolstice));
// What angle are we placed by on the year's cycle, between _latitudeAngle + _tiltAngle and -latitudeAngle + _tiltAngle?
double closestDayHeight = cos(closestDayAngleAlong) * _latitudeAngle + _tiltAngle;
double previousDayHeight = cos(previousDayAngleAlong) * _latitudeAngle + _tiltAngle;
double nextDayHeight = cos(nextDayAngleAlong) * _latitudeAngle + _tiltAngle;
// Based on that, what are the daylight durations for the three twenty-four hour days?
double closestDayDuration = day / 2 + (day / 2) * sin(closestDayHeight);
double previousDayDuration = day / 2 + (day / 2) * sin(previousDayHeight);
double nextDayDuration = day / 2 + (day / 2) * sin(nextDayHeight);
// Here we use both morning and evening for the closest day, and the previous day's morning and the next day's evening.
double closestDayMorning = closestDay + (day / 2) - (closestDayDuration / 2);
double closestDayEvening = closestDay + (day / 2) + (closestDayDuration / 2);
double previousDayEvening = previousDay + (day / 2) + (previousDayDuration / 2);
double nextDayMorning = nextDay + (day / 2) + (nextDayDuration / 2);
// We calculate the proportion along the day that we are between evening and morning (or morning and evening), along with the sooner endpoint of that interval.
double proportion;
double referenceTime;
if (distanceAlong < closestDayMorning)
{
proportion = (distanceAlong - previousDayEvening) / (closestDayMorning - previousDayEvening);
referenceTime = previousDay + day * 3 / 4;
}
else if (distanceAlong > closestDayEvening)
{
proportion = (distanceAlong - closestDayEvening) / (nextDayMorning - closestDayEvening);
referenceTime = closestDay + day * 3 / 4;
}
else
{
proportion = (distanceAlong - closestDayMorning) / (closestDayEvening - closestDayMorning);
referenceTime = closestDay + day * 1 / 4;
}
// Lastly, we take both that endpoint and the proportion of it, and we get the number of seconds according to the daylight / nighttime calculation intended.
_naturalSeconds = referenceTime + proportion * day / 2;
I was hoping to make the code clearer and easier to grasp, and I think I did that, but it is displaying similar behavior to my previous attempt: the clock hands spin by at about ten times natural time when they should be within a factor of .8 to 1.2 of standard hours/minutes/seconds.
Any advice? Has my edited code been any clearer either about what is intended or what is wrong?
Thanks,
Your code is hard to follow, but I'll try to get you some tips:
There are existing libraries out there that compute solar angle/azimuth and sunrise/sunset for a given date. Use google as a help, here's some relevant resources: http://www.esrl.noaa.gov/gmd/grad/solcalc/ If you don't find any useful source code, I could post some.
Do not use double to calculate with dates and times. That's confusing and results in errors. Use a data type that is intended to store dates.
For your code, you say that the time is running to fast. Since referenceTime and day in the last line are constant (at least for half a day), the error must be in proportion. I think you're mixing to many cases there. The interpolation should go from the start of the range to the end, so in the case
proportion = (distanceAlong - previousDayEvening) / (closestDayMorning - previousDayEvening);
referenceTime = previousDay + day * 3 / 4;
proportion should run from (previousDay + day * 3 / 4) to (closestDay + day * 3 / 4), or, described differently, from the dusk to dawn of closestDay. But it's completely unclear how this interpolation should work.
Try to draw a diagram of the different cases (I believe there should only be two, one for day and one for night) and the corresponding interpolation.
But: What are you trying to achieve after all? The resulting time is just a forward running time, it is actually independent of latitude or longitude or time of day. So to make the time run, you don't need to know where the sun is.
I'm trying to put some objects in the screen at random positions.
I use arc4random() to generate a new random number.
But it seems that the function is not working properly, here's the code and traced result:
Code :
UIView *stateView = [[UIView alloc] initWithFrame:CGRectMake( (arc4random()%700)-100 , (20 * 91) + 378 + ((arc4random()%600)+200), 325 , 188)];
NSLog(#"Note %d : X = %f , Y = %f",i,stateView.frame.origin.x,stateView.frame.origin.y);
**********************
NSLog Output :
Note 5 : X = 4294967040.000000 , Y = 2552.000000
Is this a bug or I'm doing wrong with the generator ?
According to the documentation for arc4random(), the return type is u_int32_t, which is an unsigned type. In the expression
(arc4random()%700)-100
the calculation, including the subtraction, is done using unsigned arithmetic. You are getting unsigned arithmetic overflow. To fix this, cast to a signed integer type before doing the subtraction:
((int) (arc4random() % 700)) - 100
The result of this will be an integer from -100 through 599.