I am writing some unit tests for a map coordinate function that I am writing. Unfortunately, there's something going on with XCTest that I am unable to nail down that is causing my test to fail:
NSString *testValue = #"121°31'40\"E";
double returnValue = coordinateStringToDecimal(testValue);
static double expectedValue = 121.5277777777778;
XCTAssertEqual(returnValue, expectedValue, #"Expected %f, got %f", expectedValue, returnValue);
I did read this similar question to troubleshoot. However, I am able to validate that the numbers and types are the same. Here is the console output of checking the type of each value:
(lldb) print #encode(__typeof__(returnValue))
(const char [2]) $5 = "d"
(lldb) print #encode(__typeof__(expectedValue))
(const char [2]) $6 = "d"
The Variables View in the debugger is showing them to be the same:
The interesting thing is the console output of comparing them in lldb:
(lldb) print (returnValue == expectedValue)
(bool) $7 = false
The types are the same and the actual numbers are the same. Why else would my assert be failing???
Because you are dealing with floating point numbers, there will always be a certain degree of inaccuracy, even between double values. In these cases, you need to use a different assertion: XCTAssertEqualWithAccuracy. From the docs:
Generates a failure when a1 is not equal to a2 within + or - accuracy. This test is for scalars such as floats and doubles, where small differences could make these items not exactly equal, but works for all scalars.
Change your assert to something like this:
XCTAssertEqualWithAccuracy(returnValue, expectedValue, 0.000000001);
Or in Swift 4:
XCTAssertEqual(returnValue, expectedValue, accuracy: 0.000000001, "expected better from you")
In Nimble:
expect(expectedValue).to(beCloseTo(returnValue, within: 0.000000001))
In Swift 4 accuracy was removed from the function name - now its an overload of XCTAssertEqual:
XCTAssertEqual(returnValue, expectedValue, accuracy: 0.000000001, "expected better from you")
Related
LLDB has various problems printing struct fields of double type, as documented here:
strange-behavior-in-lldb-when-printing-a-double-type-struct-member.
In my own case I tried to print a struct of type CLLocationCoordinate2D. As of Xcode 4.5.2 the error in printing CLLocationCoordinate2D persists.
Looking for ways around this bug I came across a nice macro, LOG_EXPR, in this blog:
http://vgable.com/blog/2010/08/19/the-most-useful-objective-c-code-ive-ever-written/
It does a great job of logging types into the debugger, but can't be called from the debugger.
Has anyone figured out a way to do something like LOG_EXPR while debugging in the LLDB command line interface, or any other improved printing that will work on arbitrary structs from the command line, other than switching back to GDB?
Here's what happens when I type in LLDB:
(lldb) p (CLLocationCoordinate2D)[self mapSetPointLatLon]
(CLLocationCoordinate2D) $4 = {
(CLLocationDegrees) latitude = 42.4604
(CLLocationDegrees) longitude = 42.4604
(double) easting = 42.4604
(double) northing = -71.5179
}
Notice the redundant and wrong lines added by lldb.
Here's what happens (at the same breakpoint) when I compile LOG_EXPR into my code:
Line of Code (not debugger):
LOG_EXPR(self.mapSetPointLatLon);
produces the correct output in the debugger output:
2013-01-26 14:02:17.555 S6E11[79116:c07] self.mapSetPointLatLon = {latitude=42.4604,longitude=-71.5179}
At the same breakpoint if I try to invoke LOG_EXPR from the command line, this is what happens:
(lldb) expr LOG_EXPR(self.mapSetPointLatLon);
error: use of undeclared identifier 'LOG_EXPR'
error: 1 errors parsing expression
(lldb)
Here's another example, since it turns out there is a case when you can get the debugger to do the right thing.
Here's my code fragment where I assign the struct 2 ways:
CLLocationCoordinate2D defloc = CLLocationCoordinate2DMake(kStartingLat, kStartingLon);
[[self.verticalPagingViewController mapPagingViewController] setMapSetPointLatLon: defloc];
If I just print the variable it works.
(lldb) p defloc
(CLLocationCoordinate2D) $1 = {
(CLLocationDegrees) latitude = 42.4604
(CLLocationDegrees) longitude = -71.5179
}
If I'm casting the type of the return value of an accessor method, it fails.
(lldb) p (CLLocationCoordinate2D)[[self.verticalPagingViewController mapPagingViewController] mapSetPointLatLon]
(CLLocationCoordinate2D) $2 = {
(CLLocationDegrees) latitude = 0
(CLLocationDegrees) longitude = 0
(double) easting = 0
(double) northing = 0
}
I am trying to compare a CGFloat to an integer value. Based on this value, execute a conditional... pretty standard. However, this will always be true for some reason. I even print out the values and they are clearly less than 800.... I have tried a bunch of different combinations, the most recent is shown below, I thought maybe it was comparing the size of float and the size of the int based purely on its binary values, so I tried this risky little cast operation... Any ideas?
CGPoint textViewPoint = [scroller convertPoint:[textView center] toView:(UIView *)self.view];
NSLog(#"the y coord is %f", textViewPoint.y);
int size = (int)textViewPoint.y;
NSLog(#"the yint %d", size);
//move the main view, so that the keyboard does not hide it.
//if (self.scroller.frame.origin.y >= 0 && textViewPoint.y > 800.0);
if(size > 800);
{
NSLog(#"moving up");
The problem is the ; at the end of the if(size > 800); line, not the int vs. float comparison. Remove it and all should be OK.
This is because this semicolon is interpreted as the body of your if statement, and that's this NO-OP statement that is executed when the condition is true. Then, the rest of your code next to this if empty body is outside of the if body so is executed whatever the condition value. That's exactly as if you had written:
if(size > 800)
{
}
{
NSLog(#"moving up");
}
Compiler Warning Tip
The compiler generally warns you about this mistake. Be sure that you have the "Empty Loop Bodies" warning activated in your project Build Settings (compiler flag -Wempty-body): this way the next time you do this mistake, you will have a warning about it and will know what is wrong and how to fix it.
I'm doing a small app for evaluating and analyzing transfer functions. As boring as the subject might seem to some, I want it to at least look extra cool and pro and awesome etc... So:
Step 1: Gimme teh coefficients! [A bunch of numbers]
Step 2: I'll write the polynomial with its superscripts. [The bunch of numbers in a string]
So, I write a little C parser to just print the polynomial with a decent format, for that I require a wchar_t string that I concatenate on the fly. After the string is complete I quickly try printing it on the console to check everything is ok and keep going. Easy right? Welp, I ain't that lucky...
wchar_t *polynomial_description( double *polyArray, char size, char var ){
wchar_t *descriptionString, temp[100];
int len, counter = 0;
SUPERSCRIPT superscript;
descriptionString = (wchar_t *) malloc(sizeof(wchar_t) * 2);
descriptionString[0] = '\0';
while( counter < size ){
superscript = polynomial_utilities_superscript( size - counter );
len = swprintf(temp, 100, L"%2.2f%c%c +", polyArray[counter], var, superscript);
printf("temp size: %d\n", len);
descriptionString = (wchar_t *) realloc(descriptionString, sizeof(wchar_t) * (wcslen(descriptionString) + len + 1) );
wcscat(descriptionString, temp);
counter++;
}
//fflush(stdout); //Already tried this
len = wprintf(L"%ls\n", descriptionString);
len = printf("%ls**\n", descriptionString);
len = fprintf(stdout, "%ls*\n", descriptionString);
len = printf("FFS!! Print something!");
return descriptionString;
}
During the run we can see temp size: 8 printed the expected number of times ONLY WHILE DEBUGGING, if I run the program I get an arbitrary number of prints each run. But after that, as the title states, wprintf, printf and fprintf don't print anything, yet len does change its size after each call.
In the caller function, (application:(UIApplication *)application didFinishLaunchingWithOptions:, while testing) I put an NSLog to print the return string, and I dont get ANYTHING not even the Log part.
What's happening? I'm at a complete loss.
Im on XCode 4.2 by the way.
What's the return value from printf/wprintf in the case where you think it's not printing anything? It should be returning either -1 in the case of a failure or 1 or more, since if successful, it should always print at least the newline character after the description string.
If it's returning 1 or more, is the newline getting printed? Have you tried piping the output of your program to a hex dumper such as hexdump -C or xxd(1)?
If it's returning -1, what is the value of errno?
If it turns out that printf is failing with the error EILSEQ, then what's quite likely happening is that your string contains some non-ASCII characters in it, since those cause wcstombs(3) to fail in the default C locale. In that case, the solution is to use setlocale(3) to switch into a UTF-8 locale when your program starts up:
int main(int argc, char **argv)
{
// Run "locale -a" in the Terminal to get a list of all valid locales
setlocale(LC_ALL, "en_US.UTF-8");
...
}
I'm getting this error when I'm trying to calculate the slope between two points. The user has inputted the points into text fields defined as X1,Y1,X2,Y2. Then they hit the button 'calculate'.
Here's my code where I'm getting the error
-- (IBAction)calculate:(id)sender {
self.slopeCalculate = (self.Y2.text - self.Y1.text)/(self.X2.text - self.X1.text);
}
It's specifically only pointing to 'self.X2.text' so I don't know what's going on. What am I doing wrong here?
You can't do numeric calculation on text data like NSString, you need to turn them into numerics first, such as with:
double x1Dbl = [self.X1.text doubleValue];
double x2Dbl = [self.X2.text doubleValue];
double y1Dbl = [self.Y1.text doubleValue];
double y2Dbl = [self.Y2.text doubleValue];
self.slopeCalculate = (y2Dbl - y1Dbl) / (x2Dbl - x1Dbl);
You also need to watch out for the edge case of vertical lines since these have an infinite (or undefined) slope (x2Dbl - x1Dbl will be zero).
In Xcode /Objective-C for the iPhone.
I have a float with the value 0.00004876544. How would I get it to display to two decimal places after the first significant number?
For example, 0.00004876544 would read 0.000049.
I didn't run this through a compiler to double-check it, but here's the basic jist of the algorithm (converted from the answer to this question):
-(float) round:(float)num toSignificantFigures:(int)n {
if(num == 0) {
return 0;
}
double d = ceil(log10(num < 0 ? -num: num));
int power = n - (int) d;
double magnitude = pow(10, power);
long shifted = round(num*magnitude);
return shifted/magnitude;
}
The important thing to remember is that Objective-C is a superset of C, so anything that is valid in C is also valid in Objective-C. This method uses C functions defined in math.h.