Objective C calculator displaying scientific notation - objective-c

So I've coded a calculator in objective C and I've formatted the display in .4g as I wanted only significant digits and 4 decimal places. This works fine :)
What I would like it to do is not display 2.34E+05 etc when it displays a longer number like 234,000. I've allowed it to autosize the text in the label so I know it isn't just that the label is too small.
Is there a piece of code that will make it display the actual number instead of the scientific notation?

Formatting with %f instead of %g won't use standard form.
Have a look at this specification.
Edit 1:
I found this answer to help with the rounding.
-(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;
}
I then combined these two options to get:
NSLog(#"%.0f", [self round:number toSignificantFigures:4]);
Edit 2:
What about this:
- (NSString *) floatToString:(float) val {
NSString *ret = [NSString stringWithFormat:#"%.5f", val];
unichar c = [ret characterAtIndex:[ret length] - 1];
while (c == 48 || c == 46) { // 0 or .
ret = [ret substringToIndex:[ret length] - 1];
c = [ret characterAtIndex:[ret length] - 1];
}
return ret;
}
I haven't tested this, but it looks as if it limits decimals to 5, then removes any trailing zeros or decimal points.
[Source]

Related

Decimal point with remainder

I need help with my calculator app.I'm using two float variables so when I do an exercise account, for example 6/2 the result is 3.000000 (with decimal point) and not 3 because it is a float variable. However, if I do 2/6 the result is 0.33333,How can I fix the problem that show the decimal point only if have a remainder.
Here's the code:
//Add the number to UILabel
-(IBAction)numberPressed:(UIButton *)sender {
NSString *number = sender.currentTitle;
if (self.typingNumber) {
self.firstLabel.text = [self.firstLabel.text stringByAppendingString:number];
}
else {
self.firstLabel.text = number;
self.typingNumber = YES;
}
}
//Equal method
-(IBAction)equalPress:(id)sender {
self.typingNumber = NO;
self.secondNum = [self.firstLabel.text floatValue];
result = 0;
if ([self.operation isEqualToString:#"+"]) {
result = self.firstNum + self.secondNum;
}
if ([self.operation isEqualToString:#"-"]) {
result = self.firstNum - self.secondNum;
}
if ([self.operation isEqualToString:#"X"]) {
result = self.firstNum * self.secondNum;
}
if ([self.operation isEqualToString:#"/"]) {
result = self.firstNum / self.secondNum;
}
self.firstLabel.text = [NSString stringWithFormat:#"%f" ,result];
}
You can try to use the %g format specification:
The double argument shall be converted in the style f or e (or in the style F or E in the case of a G conversion specifier), with the precision specifying the number of significant digits. If an explicit precision is zero, it shall be taken as 1. The style used depends on the value converted; style e (or E ) shall be used only if the exponent resulting from such a conversion is less than -4 or greater than or equal to the precision. Trailing zeros shall be removed from the fractional portion of the result; a radix character shall appear only if it is followed by a digit or a '#' flag is present.
from IEEE printf specification as used by Apple, emphasis added.
For example:
float a = 6.0 / 2.0;
float b = 2.0 / 6.0;
NSLog(#"%f, %g | %f, %g", a, a, b, b);
produces:
3.000000, 3 | 0.333333, 0.333333
For even more control use the NSNumberFormatter class, in particular look at properties such as alwaysShowsDecimalSeparator.
For example:
NSNumberFormatter *formatter = [NSNumberFormatter new];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
formatter.alwaysShowsDecimalSeparator = NO;
NSLog(#"%# | %#", [formatter stringFromNumber:#(a)], [formatter stringFromNumber:#(b)]);
produces:
3 | 0.333
(you can use other properties to control the number of decimal places etc.)

Find next Aloha Number

I found this problem in one of coding practice sites...Problem goes as below.
A number is said to be an aloha number if it is comprises entirely of 4s and 7s. Below are few examples of Aloha Numbers
4477
47744477
Your program will get an integer number of a non Aloha Number and your output must return the next Aloha number (in the form of string) for that input.
Example 1
Input : 1234
Output: 4444
Example 2
Input : 4472
Output: 4474
Input number represent the integer between 1 and 2*(10^9)
Input number is not Aloha Number
I tried to solve this problem as below..
- (NSString *) nextAlohaNumber:(NSUInteger) number{
// method convertNumberIntoDigit return a array of digits present in input number
NSMutableArray *numberDigits = [self convertNumberIntoDigit:number];
NSUInteger tempNum;
for(int index = 0; index < numberDigits.count; index++){
tempNum = [[numberDigits objectAtIndex:index] intValue];
if(4 != tempNum && 7 != tempNum){
if(4 > tempNum){
[numberDigits replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:4]];
}else if (7 > tempNum){
[numberDigits replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:7]];
}
else if(7 < tempNum){
[numberDigits replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:4]];
int previousIndex = index-1;
int previousNum = [[numberDigits objectAtIndex:previousIndex] integerValue];
if(previousIndex ){
if(4 == previousNum){
[numberDigits replaceObjectAtIndex:previousIndex withObject:[NSNumber numberWithInt:7]];
}
else if(7 == previousNum){
[numberDigits replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:4]];
}
}
}
}
}
return [self numberArrayToStr:numberDigits]; // convert strings with digit in Array
}
But this method doesn't pass all the test cases, for example it fails on input 4478, 790 etc.
Can any one please help me to solve this problem for all inputs with better time and space complexity.
PS: I'm ok with C,C++ code as well.
Thanks in advance.
Despite my comment above, I wondered about the "time and space complexity". It turned out to be trivial; this only takes 3 long integer variables and a single loop over each input digit (which can be incremented by this algorithm to use 1 more digit; and this will not cause an integer overflow).
Starting from the lowest digit, if it's lower than 4 replace it with 4. If it's lower than 7, replace it with 7. For 8 and 9, replace it with 4 and increment the next digit. Repeat until all digits are processed.
The following code returns the number itself for a proper "aloha" number, the next higher if not.
It requires long variables (using more than 32 bits), because the aloha number for the largest allowed input, 2*(10^9), is 4444444444 -- outside the range of a 32-bit integer.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
long not_aloha, aloha, digit;
if (argc != 2)
{
printf ("please give an aloha number\n");
return -1;
}
not_aloha = atoi (argv[1]);
printf ("not aloha: %ld\n", not_aloha);
aloha = 0;
digit = 1;
while (not_aloha)
{
if ( (not_aloha % 10) <= 4)
aloha += 4*digit;
else if ( (not_aloha % 10 ) <= 7)
aloha += 7*digit;
else
{
aloha += 4*digit;
not_aloha += 10;
}
digit *= 10;
not_aloha /= 10;
}
printf ("aloha: %ld\n", aloha);
return 0;
}

Positive/Negative button not displaying properly

I am trying to add a positive/negative button onto a numerical input in a UItextfield, but I cannot get it to function properly. What I want it to do is just add or remove a negative sign from the front of the numerical input. I am able to do that, however I cannot find a method to maintain the original number of decimal places. This is what I have tried:
- (IBAction) negsign
{
float input = [userinput.text floatValue];
float result = ((input * (-1)));
negstring = [NSString stringWithFormat:
#"%f", result];
userinput.text = negstring;
}
With this I get just a string of zeros after, like -23.0000000. I've tried limiting the decimal places by changing to #"%.2f" but I dont want extra zeros for whole integers, or rounding more than 2 decimals places. I just want it to take something like 34.658939 or 23 and make it -34.658939 or -23. Does anyone have a method to do this?
What would work best in your case is the following code:
float input = [userinput.text floatValue];
float result = ((input * (-1)));
NSNumber *resultNum = [NSNumber numberWithFloat:result];
NSString *resultString = [resultObj stringValue];
userinput.text = resultString;
If you're trying to make the number negative instead of reversing the sign, it'd be better if you replace float result = ((input * (-1))); with float result = -ABS(input);
Really, the best way to handle this would be to never convert it from a string in the first place. Just replace the first character as needed like this:
- (IBAction) negsign
{
unichar firstCharacter = [userinput.text characterAtIndex:0];
if (firstCharacter == '-') {
// Change the first character to a + sign.
userinput.text = [userinput.text stringByReplacingCharactersInRange:NSMakeRange(0, 1)
withString:#"+"];
} else if (firstCharacter == '+') {
// Change the first character to a - sign.
userinput.text = [userinput.text stringByReplacingCharactersInRange:NSMakeRange(0, 1)
withString:#"-"];
} else {
// There is no sign so we assume that it is positive.
// Insert the - at the beginning.
userinput.text = [userinput.text stringByReplacingCharactersInRange:NSMakeRange(0, 0)
withString:#"-"];
}
}

Finding the numerator of a float's fractional value, given a specific denominator [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
How to convert floats to human-readable fractions?
Convert decimal to fraction in Objective-C?
I want to take a decimal, 5.50, which is in a variable, and divide only the fractional part by 0.0625, which is my accuracy point. This would give me 8, as in 8/16 or 1/2.
Then I would like to display that answer as 5 8/16 or 1/2 in a text field. I know some answers will return a decimal still and not a whole number when dividing by .0625, but I would round that answer, which would still give me to the nearest 16th. What would be the best way to do this? I would like to make a function so I can reuse it. Yes, I posted a similar question that was answered, but wasn't able to get it to work. I'm thinking there's a better and easier way to do this, so I've posted this. Thanks in advance.
Function:
- (NSString *)theFunction:(float)input {
NSArray * array = [NSarray initWithObjects:nil,nil#"1/8",nil,#"1/4",]
int fractions = lroundf((input - (int)input)/((float)1/(float)16));
if(fractions == 0 || fractions == 16) {
return [NSString stringWithFormat:#"%d",lroundf(input)];
} else {
return [NSString stringWithFormat:#"%d %d/16",(int)input,fractions];
}
}
Note:
The if statement converts 5 0/16 into 5 and 5 16/16 into 6.
If you prefer the 5 0/16 and 5 16/16 notation, replace the if statement by:
return [NSString stringWithFormat:#"%d %d/16",(int)input,fractions];
EDIT: (by Jason)
//Just to make it a little sweeter!
- (NSString *)theFunction:(float)input {
int fractions = lroundf((input - (int)input)/((float)1/(float)16));
if(fractions == 0 || fractions == 16) {
return [NSString stringWithFormat:#"%d",lroundf(input)];
} else if(fractions == 2) {
return [NSString stringWithFormat:#"%d 1/8",(int)input];
} else if(fractions == 4) {
return [NSString stringWithFormat:#"%d 1/4",(int)input];
} else if(fractions == 6) {
return [NSString stringWithFormat:#"%d 3/8",(int)input];
} else if(fractions == 8) {
return [NSString stringWithFormat:#"%d 1/2",(int)input];
} else if(fractions == 10) {
return [NSString stringWithFormat:#"%d 5/8",(int)input];
} else if(fractions == 12) {
return [NSString stringWithFormat:#"%d 3/4",(int)input];
} else if(fractions == 14) {
return [NSString stringWithFormat:#"%d 7/8",(int)input];
} else {
return [NSString stringWithFormat:#"%d %d/16",(int)input,fractions];
}
}
EDIT (Response to edit by Jason)
I optimized your code, this way it's much cleaner.
Also check the code below, I think it's more efficient to use an array.
- (NSString *)theFunction:(float)input {
NSArray * array = [[NSArray alloc] initWithObjects: #"",#"",#"1/8",#"",#"1/4",#"",#"3/8",#"",#"1/2",#"",#"5/8",#"",#"3/4",#"",#"3/4",#"",#"7/8",#"",nil];
int fractions = lroundf((input - (int)input)/((float)1/(float)16));
if(fractions == 0 || fractions == 16) {
return [NSString stringWithFormat:#"%d",lroundf(input)];
} else {
if([[array objectAtIndex:fractions] isEqualToString:#""]) {
return [NSString stringWithFormat:#"%d %d/16",(int)input,fractions];
} else {
return [NSString stringWithFormat:#"%d %#",(int)input,[array objectAtIndex:fractions]];
}
}
}
I think your problem is much simpler than the one #Caleb linked to.
Divide by 0.0625 to get the number of sixteenths. Round the result to the nearest integer i. Use integer division i / 16 to get the number of whole units and use the modulo operator j = i % 16 to get the fractional units. To reduce the fractions, use j as an index into an array you create ahead of time as { "", "1/16", "1/8", "3/16", ... }.
You can also divide by 16 and get the modulo 16 using bitwise operators, but that will make the code harder to read for not much benefit.

obtaining objective c nsstring from c char[]

code below.
i'm tryind to obtain string answers like "a1", "c4"
this is what i'm having instead of "a1": "adresse finale: \340}00\214"
with this prinf:
printf("\nadresse finale: %s",[self convertCGPointToSquareAdress:self.frame.origin]);
the method is:
-(NSString *) convertCGPointToSquareAdress:(CGPoint ) point{
int x= point.x /PIECE_WIDTH;
int y=point.y/PIECE_WIDTH;
char lettreChiffre[2];
//char chiffre;
NSString *squareAdress;
//ascii a=97 , b=98... h=105
for (int i=97; i<105; i++) {
for (int j=8; j>0; j--) {
if(i-97==x && j-1==y ){
NSLog(#"enterrrrrrrrrred if convertCGPointToSquareAdress");
lettreChiffre[0]=i;
lettreChiffre[1]=(char) j;
printf(" lettreChiffre: %s ", lettreChiffre);
NSString *squareAdress=[NSString stringWithFormat:#"%s", lettreChiffre];
break;
}
}
}
return squareAdress;
}
can you please help me?
thanks in advance.
There are three problems I can see with your code:
1.
When you do
lettreChiffre[1]=(char) j;
remember j is a number between 1 and 8, so you're getting the ASCII character whose value is j, not the character 1...8. You should use
lettreChiffre[1]= '0' + j;
2.
lettreChiffre is a char array of length 2, which means there's no room for the terminal null character. This may work, but may give you gibberish. You should instead declare
char lettreChiffre[3];
lettreChiffre[2] = '\0';
3.
You're trying to use printf to print an NSString, which it can't do. Either use
NSLog(#"adresse finale: %#", mynsstring)
or convert the NSString back to a C-string:
printf("adresse finale: %s", [mynsstring UTF8String]);
Also, as noted by #dreamlax, you don't really need the loop. I assumed you were doing something else and ran into this trouble, so we're not really seeing the full code. But, if this is really the entirety of your code, then you can simply remove the loop as #dreamlax suggested.
What is the purpose of the loop? You have a loop that essentially brute forces a matrix to calculate the “square address”. Your method will also return an uninitialized pointer if x is greater than 8.
Your entire method could be made much simpler.
- (NSString *) convertCGPointToSquareAdress:(CGRect) point
{
unsigned int x = point.x / PIECE_WIDTH;
unsigned int y = point.y / PIECE_WIDTH;
// Do some range checking to ensure x and y are valid.
char lettreChiffre[3];
lettreChiffre[0] = 'a' + x;
lettreChiffre[1] = '1' + y;
lettreChiffre[2] = '\0';
return [NSString stringWithCString:letterChiffre encoding:NSASCIIStringEncoding];
}