issue with intvalue , floatValue - iphone

a Calculator. Each time I click on a digit button, the tag is appended to a "displaystring" nsmutable string. I ve noticed that after entering 11 digits for the same number the floatValue or intValue function give me the same error.
the self.lbldisplay.text displays the content of displaystring correctly. But the
intValue or floatValue or even the NSCanner utilities return , after entering 10 digits , the same error
here are the code and the log :
// original
[self.displayString appendString: [NSString stringWithFormat: #"%i", [sender tag]]];
else { // new entry
//origin test
[self.displayString setString:#""];
[self.displayString appendString: [NSString stringWithFormat: #"%i", [sender tag]]];
bIsTypingANumber = TRUE;
}
// fCurrentNumber = [self.displayString floatValue];
// [self display:fCurrentNumber];
// self.lblDisplay.text = displayString;
NSString *numberString;
NSString *str = [NSString stringWithString:displayString];
NSScanner *theScanner = [NSScanner scannerWithString:str];
[theScanner scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:nil];
[theScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&numberString];
NSLog(#"Attempts: %i", [numberString integerValue]);
self.lblDisplay.text = str;
Output:
2012-08-26 17:23:34.264 Pilots Fuel[4989:f803] Attempts: 1
2012-08-26 17:23:34.400 Pilots Fuel[4989:f803] Attempts: 11
2012-08-26 17:23:34.552 Pilots Fuel[4989:f803] Attempts: 111
2012-08-26 17:23:34.800 Pilots Fuel[4989:f803] Attempts: 1111
2012-08-26 17:23:34.936 Pilots Fuel[4989:f803] Attempts: 11111
2012-08-26 17:23:35.072 Pilots Fuel[4989:f803] Attempts: 111111
2012-08-26 17:23:35.216 Pilots Fuel[4989:f803] Attempts: 1111111
2012-08-26 17:23:35.344 Pilots Fuel[4989:f803] Attempts: 11111111
2012-08-26 17:23:35.488 Pilots Fuel[4989:f803] Attempts: 111111111
2012-08-26 17:23:35.632 Pilots Fuel[4989:f803] Attempts: 1111111111
2012-08-26 17:23:35.776 Pilots Fuel[4989:f803] Attempts: 2147483647
2012-08-26 17:23:36.056 Pilots Fuel[4989:f803] Attempts: 2147483647

It is because you overflow the integer data type, which can only hold values from -2147483648 to 2147483647 (32 bits in size). The double data type can hold larger values but will eventually lose precision.
Try
NSLog(#"Attempts: %lli", [numberString longLongValue]);
which will use 64 bits of precision and will allow for a larger number of digits.

Welcome to SO. Please write questions that clearly state your problem. Also, if you provide code samples, please make sure they are formatted properly so that they are more easily read by others.
Note that you are using int and float which both have size limits. They can not represent all possible numbers. You could use double and 64-bit integers, but they have a limit as well. If you really need bigger numbers, see if NSDecimalNumber will fit your use case. It does have a limit (though quite large).
If you need even bigger numbers, you will need to use a library that provides support for arbitrarily large numbers.

Related

Regex application to string?

Currently, I am looping through phone numbers to find matches in a database. However, I need to remove dashes and any area codes so that the database search can exact. Currently, I am trying to use this regex on the phone numbers :
(?:\+\d{2}\s*(?:\(\d{2}\))|(?:\(\d{2}\)))?\s*(\d{4,5}\-?\d{4})
and I am trying to apply it as such
if let longNumber = (contact.phoneNumbers.first?.value as? CNPhoneNumber)?.stringValue {
let phoneNumber = longNumber.replacingOccurrences(of: "(?:\+\d{2}\s*(?:\(\d{2}\))|(?:\(\d{2}\)))?\s*(\d{4,5}\-?\d{4})", with: "$1", options: .regularExpression)
However, I receive the error Invalid escape sequence in literal and Missing argument for parameter 'for' in call
How can I properly get only the phone digits from the string? ie if it is +1 300-300-3000
I need it to return 3003003000.
Examples:
+1 390 - 456 - 8823 -> 3904568823
+92 084 765 4902 --> 0847654902
+922 (064) 864 0921 --> 0648640921
842.231.9072 --> 8422319072
+1 (972) - 864 - 0921 --> 9728640921
+92 33 - 783 - 9382 --> 337839282
From the examples you have shown, I assume the following rules:
Phone numbers are formatted in 3 or 4 parts
Part1 (optional)
+
1 to 3 digits
one or more whitespaces follow
Part2
May be enclosed in ( and )
2 or 3 digits
a hyphen or a decimal point or a whitespace with extra whitespaces at both ends follows
Part3
3 digits
a hyphen or a decimal point or a whitespace with extra whitespaces at both ends follows
Part4
4 digits
(Please remember, this sort of phone number notation rule is local to a specific region. When you want to internationalize your app, you may need many more rules. The pattern you have now may be written for some other region.)
Partial pattern for each part would be something as follows:
let part1 = "(?:\\+\\d{1,3}\\s+)?"
let part2 = "(?:\\((\\d{2,3})\\)|(\\d{2,3}))\\s*[\\s\\.-]?\\s*"
let part3 = "(\\d{3})\\s*[\\s\\.-]?\\s*"
let part4 = "(\\d{4})"
(Please do not miss that all backslashes are escaped.)
Testing code:
import Foundation
let numbers: [(long: String, expected: String)] = [
("+1 300-300-3000", "3003003000"),
("+1 390 - 456 - 8823", "3904568823"),
("+92 084 765 4902", "0847654902"),
("+922 (064) 864 0921", "0648640921"),
("842.231.9072", "8422319072"),
("+1 (972) - 864 - 0921", "9728640921"),
("+92 33 - 783 - 9382", "337839382"), //I assume your example is wrong here
]
for number in numbers {
let longNumber = number.long
let part1 = "(?:\\+\\d{1,3}\\s+)?"
let part2 = "(?:\\((\\d{2,3})\\)|(\\d{2,3}))\\s*[\\s\\.-]?\\s*"
let part3 = "(\\d{3})\\s*[\\s\\.-]?\\s*"
let part4 = "(\\d{4})"
let pattern = "^\(part1)\(part2)\(part3)\(part4)$"
let phoneNumber = longNumber.replacingOccurrences(of: pattern, with: "$1$2$3$4", options: .regularExpression)
print("\(longNumber) --> \(phoneNumber)", phoneNumber == number.expected ? "Success" : "Fail (expected \(number.expected))")
}
Output:
+1 300-300-3000 --> 3003003000 Success
+1 390 - 456 - 8823 --> 3904568823 Success
+92 084 765 4902 --> 0847654902 Success
+922 (064) 864 0921 --> 0648640921 Success
842.231.9072 --> 8422319072 Success
+1 (972) - 864 - 0921 --> 9728640921 Success
+92 33 - 783 - 9382 --> 337839382 Success
The code above may not work as expected for possible other inputs, please try to fix it to fit for such inputs by yourself.

Two byte report count for hid report descriptor

I'm trying to create an HID report descriptor for USB 3.0 with a report count of 1024 bytes.
The documentation at usb.org for HID does not seem to mention a two byte report count. Nonetheless, I have seen some people use 0x96 (instead of 0x95) to enter a two byte count, such as:
0x96, 0x00, 0x02, // REPORT_COUNT (512)
which was taken from here:
Custom HID device HID report descriptor
Likewise, from this same example, 0x26 is used for a two byte logical maximum.
Where did this 0x96 and 0x26 field come from? I don't see any documentation for it.
REPORT_COUNT is defined in the Device Class Definition for HID 1.11 document in section 6.2.2.7 Global Items on page 36 as:
Report Count 1001 01 nn Unsigned integer specifying the number of data
fields for the item; determines how many fields are included in the
report for this particular item (and consequently how many bits are
added to the report).
The nn in the above code is the item length indicator (bSize) and is defined earlier in section 6.2.2.2 Short Items as:
bSize Numeric expression specifying size of data:
0 = 0 bytes
1 = 1 byte
2 = 2 bytes
3 = 4 bytes
Rather confusingly, the valid values of bSize are listed in decimal. So, in binary, the bits for nn would be:
00 = 0 bytes (i.e. there is no data associated with this item)
01 = 1 byte
10 = 2 bytes
11 = 4 bytes
Putting it all together for REPORT_COUNT, which is an unsigned integer, the following alternatives could be specified:
1001 01 00 = 0x94 = REPORT_COUNT with no length (can only have value 0?)
1001 01 01 = 0x95 = 1-byte REPORT_COUNT (can have a value from 0 to 255)
1001 01 10 = 0x96 = 2-byte REPORT_COUNT (can have a value from 0 to 65535)
1001 01 11 = 0x97 = 4-byte REPORT_COUNT (can have a value from 0 to 4294967295)
Similarly, for LOGICAL_MAXIMUM, which is a signed integer (usually, there is an exception):
0010 01 00 = 0x24 = LOGICAL_MAXIMUM with no length (can only have value 0?)
0010 01 01 = 0x25 = 1-byte LOGICAL_MAXIMUM (can have a values from -128 to 127)
0010 01 10 = 0x26 = 2-byte LOGICAL_MAXIMUM (can have a value from -32768 to 32767)
0010 01 11 = 0x27 = 4-byte LOGICAL_MAXIMUM (can have a value from -2147483648 to 2147483647)
The specification is unclear on what value a zero-length item defaults to in general. It only mentions, at the end of section 6.2.2.4 Main Items, that MAIN item types and, within that type, INPUT item tags, have a default value of 0:
Remarks - The default data value for all Main items is zero (0).
- An Input item could have a data size of zero (0) bytes. In this case the value of
each data bit for the item can be assumed to be zero. This is functionally
identical to using a item tag that specifies a 4-byte data item followed by four
zero bytes.
It would be reasonable to assume 0 as the default for other item types too, but for REPORT_COUNT (a GLOBAL item) a value of 0 is not really a sensible default (IMHO). The specification doesn't really say.

Why doesn't my NSOutputStream have space available after the first write? (hasSpaceAvailable becomes NO)

With NSOutputStream I get to write perfectly just the first time.
Here is the method to send data:
- (NSInteger)sendVsCommand:(VsCommand *)command
{
NSData *commandArray = [NSData dataWithData:[command getCommandArray]];
NSLog(#"Space availiable: %d", [writeStream hasSpaceAvailable]);
NSInteger result = [writeStream write:[commandArray bytes]
maxLength:[commandArray length]];
NSLog(#"Writing result: %d", result);
return result;
}
And here is the handling of the events:
case NSStreamEventHasSpaceAvailable:
NSLog(#"%# can accept bytes", aStream);
if (aStream == writeStream) {
NSLog(#"Can send data: %d", [writeStream hasSpaceAvailable]);
}
break;
Just the 'case' that matters anyway.
Here are the results in the console:
2013-08-16 18:07:12.769 hMonitor[5765:307] <__NSCFInputStream: 0x148650> is open
2013-08-16 18:07:12.776 hMonitor[5765:307] <__NSCFOutputStream: 0x148330> is open
2013-08-16 18:07:12.777 hMonitor[5765:307] <__NSCFOutputStream: 0x148330> can accept bytes
2013-08-16 18:07:12.779 hMonitor[5765:307] Can send data: 1
2013-08-16 18:07:13.107 hMonitor[5765:307] <__NSCFInputStream: 0x148650> has bytes
2013-08-16 18:07:13.112 hMonitor[5765:307] Space availiable: 1
2013-08-16 18:07:13.116 hMonitor[5765:307] Writing result: 41
2013-08-16 18:07:13.118 hMonitor[5765:307] <__NSCFOutputStream: 0x148330> can accept bytes
2013-08-16 18:07:13.119 hMonitor[5765:307] Can send data: 1
2013-08-16 18:07:13.687 hMonitor[5765:307] <__NSCFInputStream: 0x148650> has bytes
2013-08-16 18:07:15.343 hMonitor[5765:307] Space availiable: 0
2013-08-16 18:07:15.345 hMonitor[5765:307] Writing result: 0
As you can see, when the streams open, I can write just fine (Can
send data: 1).
Then I receive some data, and write a response immediately, Space
availiable: 1 and Writing result: 41.
Almost immediately the OutputStream is free to write again, Can send
data: 1 (but I don't need to send anything, until the user makes
some selection). And I get a response very quickly.
Finally, I try to write again (2 seconds later because that's when
the user has made a selection). However, now the Space available is
NO, and the Writing result is 0.
Any ideas? Where do you recommend I should look?
Thanks in advance.
My pointers were becoming nil, because I was not handling them the right way.
Just goes to show how green I am in Objective-C.

NSRegularExpression to validate URL

I found this regular expression on a website. It is said to be the best URL validation expression out there and I agree. Diego Perini created it.
The problem I am facing is when trying to use it with objective-C to detect URLs on strings. I have tried using options like NSRegularExpressionAnchorsMatchLines, NSRegularExpressionIgnoreMetacharacters and others, but still no luck.
Is the expression not well formatted for Objective-C? Am I missing something? Any ideas?
I have tried John Gruber's regex, also, but it fails with some invalid URLs.
Regular Expression Explanation of expression
^ match at the beginning
//Protocol identifier
(?:
(?:https?|ftp http, https or ftp
):\\/\\/ ://
)? optional
// User:Pass authentication
(?:
^\\s+ non white spaces, 1 or more times
(?:
:^\\s* : non white spaces, 0 or more times, optionally
)?# #
)? optional
//Private IP Addresses ?! Means DO NOT MATCH ahead. So do not match any of the following
(?:
(?!10 10 10.0.0.0 - 10.999.999.999
(?:
\\.\\d{1,3} . 1 to 3 digits, three times
){3}
)
(?!127 127 127.0.0.0 - 127.999.999.999
(?:
\\.\\d{1,3} . 1 to 3 digits, three times
){3}
)
(?!169\\.254 169.254 169.254.0.0 - 169.254.999.999
(?:
\\.\\d{1,3} . 1 to 3 digits, two times
){2}
)
(?!192\\.168 192.168 192.168.0.0 - 192.168.999.999
(?:
\\.\\d{1,3} . 1 to 3 digits, two times
){2}
)
(?!172\\. 172. 172.16.0.0 - 172.31.999.999
(?:
1[6-9] 1 followed by any number between 6 and 9
| or
2\\d 2 and any digit
| or
3[0-1] 3 followed by a 0 or 1
)
(?:
\\.\\d{1,3} . 1 to 3 digits, two times
){2}
)
//First Octet IPv4 // match these. Any non network or broadcast IPv4 address
(?:
[1-9]\\d? any number from 1 to 9 followed by an optional digit 1 - 99
| or
1\\d\\d 1 followed by any two digits 100 - 199
| or
2[01]\\d 2 followed by any 0 or 1, followed by a digit 200 - 219
| or
22[0-3] 22 followed by any number between 0 and 3 220 - 223
)
//Second and Third Octet IPv4
(?:
\\. .
(?:
1?\\d{1,2} optional 1 followed by any 1 or two digits 0 - 199
| or
2[0-4]\\d 2 followed by any number between 0 and 4, and any digit 200 - 249
| or
25[0-5] 25 followed by any numbers between 0 and 5 250 - 255
)
){2} two times
//Fourth Octet IPv4
(?:
\\. .
(?:
[1-9]\\d? any number between 1 and 9 followed by an optional digit 1 - 99
| or
1\\d\\d 1 followed by any two digits 100 - 199
| or
2[0-4]\\d 2 followed by any number between 0 and 4, and any digit 200 - 249
| or
25[0-4] 25 followed by any number between 0 and 4 250 - 254
)
)
//Host name
| or
(?:
(?:
[a-z\u00a1-\uffff0-9]+-? any letter, digit or character one or more times with optional -
)* zero or more times
[a-z\u00a1-\uffff0-9]+ any letter, digit or character one or more times
)
//Domain name
(?:
\\. .
(?:
[a-z\u00a1-\uffff0-9]+-? any letter, digit or character one or more times with optional -
)* zero or more times
[a-z\u00a1-\uffff0-9]+ any letter, digit or character one or more times
)* zero or more times
//TLD identifier
(?:
\\. .
(?:
[a-z\u00a1-\uffff]{2,} any letter, digit or character more than two times
)
)
)
//Port number
(?:
:\\d{2,5} : followed by any digit, two to five times, optionally
)?
//Resource path
(?:
\\/[^\\s]* / followed by an optional non space character, zero or more times
)? optional
$ match at the end
EDIT
I think I forgot to say that I am using the expression in the following code: (partial code)
NSError *error = NULL;
NSRegularExpression *detector = [NSRegularExpression regularExpressionWithPattern:[self theRegularExpression] options:0 error:&error];
NSArray *links = [detector matchesInString:theText options:0 range:NSMakeRange(0, theText.length)];
^(?i)(?:(?:https?|ftp):\\/\\/)?(?:\\S+(?::\\S*)?#)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?$
Is the best URL validation regular expression I found and it is explained on my question. It is already formatted to work on Objective-C. However, using it with NSRegularExpression gave me all sorts of problems, including my app crashing. RegexKitLite had no problems handling it. I do not know if it is a size limitation or some flag not being set.
My final code looked like:
//First I take the string and put every word in an array, then I match every word with the regular expression
NSArray *splitIntoWordsArray = [textToMatch componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewLineCharacterSet]];
NSMutableString *htmlString = [NSMutableString stringWithString:textToMatch];
for (NSString *theText in splitIntoWordsArray){
NSEnumerator *matchEnumerator = [theText matchEnumeratorWithRegex:theRegularExpressionString];
for (NSString *temp in matchEnumerator){
[htmlString replaceOccurrencesOfString:temp withString:[NSString stringWithFormat:#"%#", temp, temp] options:NSLiteralSearch range:NSMakeRange(0, [htmlString length])];
}
}
[htmlString replaceOccurrencesOfString:#"\n" withString:#"<br />" options:NSLiteralSearch range:NSMakeRange(0, htmlString.length)];
//embed the text on a webView as HTML
[webView loadHTMLString:[NSString stringWithFormat:embedHTML, [mainFont fontName], [mainFont pointSize], htmlString] baseURL:nil];
The result: a UIWebView with some embedded HTML, where URLs and emails are clickable. Do not forget to set dataDetectorTypes = UIDataDetectorTypeNone
You can also try
NSError *error = NULL;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:#"(?i)(?:(?:https?):\\/\\/)?(?:\\S+(?::\\S*)?#)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?" options:NSRegularExpressionCaseInsensitive error:&error];
if (error)
NSLog(#"error");
NSString *someString = #"This is a sample of a sentence with a URL http://. http://.. http://../ http://? http://?? http://??/ http://# http://-error-.invalid/ http://-.~_!$&'()*+,;=:%40:80%2f::::::#example.com within it.";
NSRange range = [expression rangeOfFirstMatchInString:someString options:NSMatchingCompleted range:NSMakeRange(0, [someString length])];
if (!NSEqualRanges(range, NSMakeRange(NSNotFound, 0))){
NSString *match = [someString substringWithRange:range];
NSLog(#"%#", match);
}
else {
NSLog(#"no match");
}
Hope it helps somebody in the future
The regular expression will sometimes cause the application to hang, so I decided to use gruber's regular expression modified to recognize url without protocol or the www part:
(?i)\\b((?:[a-z][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/?)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))*(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’])*)
Am I missing something?
You're missing the built-in stuff to do this for you. There's a handy object called NSDataDetector. You create it to look for certain data "types" (like, say, NSTextCheckingTypeLink), then ask it for its -matchesInString:options:range:.
Here's an earlier answer of mine showing how to use it.

Perfomance slowdown with growth of operations number

I have next problem. My code performance depends on number of operation! How can it be? (I use gcc v 4.3.2 under openSuse 11.1)
Here is my code:
#define N_MAX 1000000
typedef unsigned int uint;
double a[N_MAX];
double b[N_MAX];
uint n;
int main(){
for (uint i=0; i<N_MAX; i++) {
a[i]=(double)rand()/RAND_MAX;
}
for (uint n=100000; n<500000; n+=5000) {
uint time1 = time(NULL);
for (uint i=0; i<n;++i)
for (uint j=0;j<n;++j)
b[j] = a[j];
uint time2 = time(NULL);
double time = double(time2-time1);
printf("%5d ", n);
printf("%5.2f %.3f\n", time, ((double)n*n/time)/1e9);
}
return 0;
}
And here is the log of results:
n-time-Gflops (=)
200000 23.00 1.739
205000 24.00 1.751
210000 25.00 1.764
215000 26.00 1.778
220000 27.00 1.793
225000 29.00 1.746
230000 30.00 1.763
235000 32.00 1.726
240000 32.00 1.800
245000 34.00 1.765
250000 36.00 1.736
255000 37.00 1.757
260000 38.00 1.779
265000 40.00 1.756
270000 42.00 1.736
275000 44.00 1.719
280000 46.00 1.704
285000 48.00 1.692
290000 49.00 1.716
295000 51.00 1.706
300000 54.00 1.667
305000 54.00 1.723
310000 59.00 1.629
315000 61.00 1.627
320000 66.00 1.552
325000 71.00 1.488
330000 76.00 1.433
335000 79.00 1.421
340000 84.00 1.376
345000 85.00 1.400
350000 89.00 1.376
355000 96.00 1.313
360000 102.00 1.271
365000 110.00 1.211
370000 121.00 1.131
375000 143.00 0.983
380000 156.00 0.926
385000 163.00 0.909
There is also the image but I can't post it cause of new users restrictions. But here is the log plot.
What is the reason of this slowdown?
How to get rid of it? Please Help!
Your inner loops increase number of iterations every time - it is expected to take more time to do their job if there is more calculations to do. First time there are 100k operations to be done, second time 105k operations, and so on. It simply must take more and more time.
EDIT: To be clearer, I tried to say it looks to something that Spolsky called Shlemiel the painter's algorithm
Thank a lot for response!
My expectation bases on idea that operation number per time unit should remains the same. So if I increase number of operations, say twice, then computation time should increase also twice, therefore the ration of operations number and the computation time should be constant. This is something that i didn't meet. :(