Double with complete whole number - iphone

I am making a iphone calculator app and I ran into this issue which I cannot seem to find a solution for.
When user enters numbers I convert them into double and then I convert that double result into a string. I am using %g to get whole numbers. The problem I have is for large numbers it shows a "E" exponent. This is what I have tried so far
NSLog(#"Num1: %g", 5000.0*8.0);
NSLog(#"Num2: %g", 500000.0*85.0);
NSLog(#"Num3: %f", 500000.0*85.0);
NSLog(#"Num4: %.4f", 5000.0*8.0);
NSLog(#"Num5: %.4f", 500000.0*85.0);
NSLog(#"Num6: %g", 5000000.0/3.7);
NSLog(#"Num7: %.4f", 5000000.0/3.7);
This is what I get in terms of results
2013-10-20 14:09:34.261 ECalc[9947:a0b] Num1: 40000
2013-10-20 14:09:34.262 ECalc[9947:a0b] Num2: 4.25e+07
2013-10-20 14:09:34.263 ECalc[9947:a0b] Num3: 42500000.000000
2013-10-20 14:09:34.264 ECalc[9947:a0b] Num4: 40000.0000
2013-10-20 14:09:34.264 ECalc[9947:a0b] Num5: 42500000.0000
2013-10-20 14:09:34.265 ECalc[9947:a0b] Num6: 1.35135e+06
2013-10-20 14:09:34.266 ECalc[9947:a0b] Num7: 1351351.3514
Just like a normal calculator I would like to show whole numbers when numbers are multiplied normally. i.e.
Num2 = 42500000
Num7 = 1351351.3514
So here's my question, is there a string format specifier that I can use that will fit both num2 and num7 results? Do I need to use a lot of logic to see if the numbers after dot are zero then truncate them otherwise keep them and use %.4f?

So, here's a quick and dirty solution to what you need.
double num1 = 5000.0*8.0;
double num7 = 5000000.0/3.7;
int decimalPlaces = 4;
if ((int) num1 == num1)
NSLog(#"Num1: %0.0f",num1);
else
NSLog(#"Num1: %0.*f", decimalPlaces, num1);
if ((int) num7 == num7)
NSLog(#"Num1: %0.0f",num7);
else
NSLog(#"Num1: %0.*f", decimalPlaces, num7);
But then you seemed to be concerned with actually being able to split up an NSString as well. So, the first block of code is the direction I recommend. If you're choosing to keep things complicated and stay within NSString throughout your calculator, then you can create a class that will split up an NSString and return to you either the whole number or the number with all its decimals. What I'm giving here is more than you need, but since you're new to iOS, hopefully it'll help you learn, there's a lot more you can do with this too, if you so desire.
-(NSString *)noZeroes:(NSString *)number
{
int i = 0, decimalPos = 0;
//NSRange says {startHere, forThisManyCharacters}
NSRange subRange = {i, 1};
NSString *substr = [number substringWithRange:subRange];
while (i<[number length] && !([substr isEqualToString:#"."]))
{
i++;
NSRange subRange = {i, 1};
substr = [number substringWithRange:subRange];
}
//No decimal point in this number
if (i == [number length])
return number; //so return the number as is
decimalPos = i+1;
NSRange decimalRange = {decimalPos, [number length] - decimalPos};
NSString *decimals = [number substringWithRange:decimalRange];
NSRange wholeNumRange = {0, decimalPos};
NSString *wholeNums =[number substringWithRange:wholeNumRange];
//Numbers you don't want, you can put anything within a CharacterSet like this
NSCharacterSet *notZeroes = [NSCharacterSet characterSetWithCharactersInString:#"123456789"];
NSRange range = [decimals rangeOfCharacterFromSet:notZeroes];
if (range.location == NSNotFound) {
// nothing but zeroes in the string
return wholeNums;
} else {
// nonzeroes are present
return number;
}
}
You would call this with something like:
NSString *Num1 = #"22345.56"
NSString *truncatedNum1 = [self noZeroes:Num1];
NSLog(#"Num1: %#", truncatedNum1);

Related

Objective C : Get correct float values(justified)

I worked a lot in it and can't find a solution. Even the title can't explain clearly.
I have three values weight, quantity and total
I had done the following
float wq = [[weightarray objectAtIndex:selectedint]floatValue];
float q = [quantity floatValue];
float total = wq * q;
for ex, if
[weightarray objectAtIndex:selectedint] = #"3.14";
quantity = 4;
then the result is
wq = 3.140000 q= 4.000000 total = 12.560000
but I need
wq = 3.14 total = 12.56
what to do?
I searched a lot, someone suggests to use NSDecimal,
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:2 raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];
but the scale is not 2 here, wq value may have 3 or four numbers after point.
If the total = 2.30000100 means I need total = 2.300001
how to solve this?
I'm not entirely sure what it is your asking for, but it seems as if you want the values to only display a 2 d.p. In which case you could use a string format like so:
NSString *output = [NSString stringWithFormat:#"float = %.2f", 3.14];
The .2 specifies that the float should be justified to 2 d.p.
Hope this helps
There may be a more direct way to achieve it (which I don't know) but here's a suggestion...
Convert to string as you already do.
Use [myString hasSuffix:#"0"] to see if it ends in zero.
Use [myString substringToindex:[myString length]-1] to create a new string without the final zero.
Repeat.
I know it's not elegant, but unless someone has a better solution, this will at least do what you want.
UPDATE: scratch that - I just discovered [myString stringByTrimmingCharactersInSet:set]. Surely this must be what you need...?
Finally solution found, thanks to Martin
float total = 12.56000;
NSString *s = [NSString stringWithFormat:#"%f", total];
NSLog(#"%#",s);
BOOL success;
success =NO;
while(!success)
{
if ([s hasSuffix:#"0"])
{
s = [s substringWithRange:NSMakeRange(0,[s length]-1)];
}
else if ([s hasSuffix:#"."])
{
s = [s substringWithRange:NSMakeRange(0,[s length]-1)];
success = YES;
}
else
success = YES;
}
NSLog(#"%#",s);
if total = 12.560000 it returns total = 12.56
if total = 12.000000 it returns total = 12
if total = 10.000000 it returns total = 10
if total = 12.3000100 it returns total = 12.30001

Obj-C, How do I handle version number with 4 parts?, greater than etc

I know this isn't going to be a challenging exercise, but I thought I'd ask, just in case there's some methods already in objective-c etc.
In my app I only handle a 2 number version number e.g. 1.5
I want to upgrade this to 4 numbers which could have up to 4 digits.
So I need to handle existing numbers and return true of false when passed database version and the bundle version numbers.
At the moment I simply do
NSString *strOnePointFive = #"1.5";
if (dblDBVersion < [strOnePointFive doubleValue]) {
}
This is a duplicate, was in other formats. Here are some answers to how to handle the version numbers, either equal, greater or below the required version number. Which is answer in this link..
NSString *reqSysVer = #"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
isSupported = YES;
else
isSupported = NO;
What I do is take that string and break it into components:
NSArray *array = [myVersion componentsSeparatedByCharactersInSet:#"."];
NSInteger value = 0;
NSInteger multiplier = 1000000;
for(NSString *n in array) {
value += [n integerValue] * multiplier;
multiplier /= 100;
}
What this does is give you a normalized value you can use for comparison, and will generally compare releases that have different "depths", ie 1.5 and 1.5.2.
It breaks if you have more than 100 point releases (ie any number is > 100) and also will declare 1.5.0 == 1.5. That said, its short, sweet, and simple to use.
EDIT: if you use the NSString 'compare:options:' method, make sure you have your string well groomed:
s1 = #"1.";
s2 = #"1";
NSLog(#"Compare %# to %# result %d", s1, s2, (int)[s1 compare:s2 options:NSNumericSearch]);
s1 = #"20.20.0";
s2 = #"20.20";
NSLog(#"Compare %# to %# result %d", s1, s2, (int)[s1 compare:s2 options:NSNumericSearch]);
2012-09-06 11:26:24.793 xxx[59804:f803] Compare 1. to 1 result 1
2012-09-06 11:26:24.794 xxx[59804:f803] Compare 20.20.0 to 20.20 result 1

Format a String in IPhone

I need to add space after every 4 characters in a string.. For example if the string is aaaaaaaa, i need to format it as aaaa aaaa. I tried the following code, but it doesn't work for me.
NSMutableString *currentFormattedString = [[NSMutableString alloc] initWithString:formattedString];
int count = [formattedString length];
for (int i = 0; i<count; i++) {
if ( i %4 == 0) {
[currentFormattedString insertString:#" " atIndex:i];
}
}
Can anyone help me with this?
You haven't said what isn't working with your code, so it's hard to know exactly what to answer. As a tip - in future questions don't just say "it isn't working", but state WHAT isn't working and HOW it isn't working. However...
NSMutableString *currentFormattedString = [[NSMutableString alloc] initWithString:formattedString];
int count = [formattedString length];
for (int i = 0; i<count; i++) {
if ( i %4 == 0) {
[currentFormattedString insertString:#" " atIndex:i];
}
}
You are inserting a space, but you are not then accounting for this in your index value. So, suppose your formattedString is aaaaaaaaaaaaaaaa
The first time through your loop, you will get to the 4th position and insert a space at i=4
aaaa aaaaaaaaaaaa
Now the next time you get to insert a space, i will be 8. But the 8th position in your currentFormattedString isn't where you think it will be
aaaa aaa aaaaaaaaa
Next time it will be another 4 characters along which still isn't where you think
aaaa aaa aa aaaaaaa
And so on
You have to take into account the inserted space which will affect the offset value.
NSString *text = [[NSString alloc] initWithString:#"aaaaaaaa"];
NSString *result = [[NSString alloc] init];
double count = text.length/4;
if (count>1) {
for (int i = 0; i<count; i++) {
result = [NSString stringWithFormat:#"%#%# ",result,[text substringWithRange:NSMakeRange(i*4, 4)]];
}
result = [NSString stringWithFormat:#"%#%# ",result,[text substringWithRange:NSMakeRange(((int)count)*4, text.length-((int)count)*4)]];
}
else result = text;
I found the following which formats a string to a telephone number format, but it looks like you could easily change it to support other formats
Telephone number string formatting
Nick Bull answered on the reasons why your method broke already.
IMHO the appropriate solution would be to use a while loop and do the loop increments yourself.
NSInteger i = 4; // first #" " should be inserted after the 4th (index = 3) char
while (i < count) {
[currentFormattedString insertString:#" " atIndex:i];
count ++; // you did insert #" " so the length of the string increased
i += 5; // you now must skip 5 (" 1234") characters
}

Converting decimal to binary

I want to convert decimal number in binary number. I'm using this method:
- (NSMutableString*)intStringToBinary:(long long)element{
NSMutableString *str = [[NSMutableString alloc] initWithString:#""];
for(NSInteger numberCopy = element; numberCopy > 0; numberCopy >>= 1)
{
[str insertString:((numberCopy & 1) ? #"1" : #"0") atIndex:0];
}
return str;
}
everything is going fine if the number "element" is >0. If the number is <0 there is the problem. For examle the method can't convert the number "-1". What can i do to solve the problem? Thanks in advance!!
You need an extra bit for the sign.
Example:
1xxxx represents the binary number + xxxx.
0yyyy represents the binary number - yyyy.
Here is a way to do it in Python using Wallar's Algorithm. The input and output are lists.
from math import *
def baseExpansion(n,c,b):
j = 0
base10 = sum([pow(c,len(n)-k-1)*n[k] for k in range(0,len(n))])
while floor(base10/pow(b,j)) != 0: j = j+1
return [floor(base10/pow(b,j-p)) % b for p in range(1,j+1)]

What is a good way to remove the formatting from a phone number to only get the digits?

Is there a better or shorter way of striping out all the non-digit characters with Objective-C on the iPhone?
NSString * formattedNumber = #"(123) 555-1234";
NSCharacterSet * nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
NSString * digits;
NSArray * parts = [formattedNumber componentsSeparatedByCharactersInSet:nonDigits];
if ( [parts count] > 1 ) {
digits = [parts componentsJoinedByString:#""];
} else {
digits = [parts objectAtIndex:0];
}
return digits;
You could use a RegEx-replacement that replaces [\D] with nothing.
Dupe of Remove all but numbers from NSString
The accepted answer there involves using NSScanner, which seems heavy-handed for such a simple task. I'd stick with what you have there (though someone in the other thread suggested a more compact version if it, thus:
NSString *digits = [[formattedNumber componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:#""];
Phone numbers can contain asterisks and number signs (* and #), and may start with a +. The ITU-T E-123 Recommandation recommends that the + symbol be used to indicate that the number is an international number and also to serve as a reminder that the country-specific international dialling sequence must be used in place of it.
Spaces, hyphens and parentheses cannot be dialled so they do not have any significance in a phone number. In order to strip out all useless symbols, you should remove all characters not in the decimal character set, except * and #, and also any + not found at the start of the phone number.
To my knowledge, there is no standardised or recommended way to represent manual extensions (some use x, some use ext, some use E). Although, I have not encountered a manual extension in a long time.
NSUInteger inLength, outLength, i;
NSString *formatted = #"(123) 555-5555";
inLength = [formatted length];
unichar result[inLength];
for (i = 0, outLength = 0; i < inLength; i++)
{
unichar thisChar = [formatted characterAtIndex:i];
if (iswdigit(thisChar) || thisChar == '*' || thisChar == '#')
result[outLength++] = thisChar; // diallable number or symbol
else if (i == 0 && thisChar == '+')
result[outLength++] = thisChar; // international prefix
}
NSString *stripped = [NSString stringWithCharacters:result length:outLength];
You could do something like this:
NSString *digits = [[formattedNumber componentsSeparatedByCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:#""];
Noting 0xA3's comment above, you could optionally use a different NSCharacterSet that includes + and other non-digits that are valid in phone numbers.