I know this has been asked a few times in the past but everything I try is failing. I have a custom numeric keypad with a UILabel. When I hit the '1' the UILabel displays a one. Now here's what I'm trying to do:
When I hit the '1' button I want: 0.01 in the UILabel
Followed by a '4' button I want: 0.14 in the UILabel
Then a '6': 1.46
etc, etc.
Now the keyboard and UILabel are working great. I just need to get the decimal's working now. Any sample code would be great, (and where I should place it in my application). Let me know if you want to see my code thus far. Pretty straightforward. Thanks everyone!
Here's about how I would do it:
#define NUMBER_OF_DECIMAL_PLACES 2
NSMutableArray *typedNumbers = ...; //this should be an ivar
double displayedNumber = 0.0f; //this should also be an ivar
//when the user types a number...
int typedNumber = ...; //the number typed by the user
[typedNumbers addObject:[NSNumber numberWithInt:typedNumber]];
displayedNumber *= 10.0f;
displayedNumber += (typedNumber * 1e-NUMBER_OF_DECIMAL_PLACES);
//show "displayedNumber" in your label with an NSNumberFormatter
//when the user hits the delete button:
int numberToDelete = [[typedNumbers lastObject] intValue];
[typedNumbers removeLastObject];
displayedNumber -= (numberToDelete * 1e-NUMBER_OF_DECIMAL_PLACES);
displayedNumber /= 10.0f;
//show "displayedNumber" in your label with an NSNumberFormatter
Typed in a browser. Caveat Implementor. Bonus points for using NSDecimal instead of a double.
Explanation of what's going on:
We're essentially doing bit shifting, but in base 10 instead of base 2. When the user types a number (ex: 6), we "shift" the existing number left one decimal place (ex: 0.000 => 00.00), multiply the typed number by 0.01 (6 => 0.06), and add that to our existing number (00.00 => 00.06). When the user types in another number (ex: 1), we do the same thing. Shift left (00.06 => 00.60), multiply the typed number by 0.01 (1 => 0.01), and add (00.60 => 00.61). The purpose of storing the number is an NSMutableArray is simply a convenience to make deletion easier. It's not necessary, however. Just a convenience.
When the user hits the delete button (if there is one), we take the last number entered (ex: 1), multiply it be 0.01 (1 => 0.01), subtract it from our number (0.61 => 0.6), and then shift our number right one decimal place (0.6 => 0.06). Repeat this as long as you've got numbers in your array of entered numbers. Disable the delete button when that array is empty.
The suggestion to use NSDecimal is simply to allow for very high precision numbers.
Related
I design setting for amount section so my requirements are: 1. the default Amount shall be $0.00. and 2. the max amount shall be $99999.99 and 3. when an amount is entered using the numerical keyboard,the amount shall get populated from right side of the decimal point (cents) to the left side of decimal point(Dollar). For e.g default value is $0.00 and when i put 1 then it should show $0.01 And when i put 2 it should show $0.12 and after that For 3 it should show $1.23 and so on to $99999.99.
I am not sure but i think this method should used
-(void)textFieldDidEndEditing:(UITextField *)textField
OR
- (BOOL)textFieldShouldReturn:(UITextField *)textField.
I am little bit weak in coding if possible please give me answer in code that would be better for me.
How can i get this? Need help.
Thanks
-(IBAction)btnPointPress:(id)sender
{
if([stringMain length] < 10)
{
stringMain = [[NSString stringWithFormat:stringMain]stringByAppendingFormat:#"."];
pointCheck = YES;
pointOnce++;
}
lastString = stringMain;
number = [stringMain doubleValue];
}
This is for adding a decimal point. Now tell me after this what is your requirement ?
I am trying to make an analysis app which calculates percentages of winners etc. Please see the attached picture:
So when there is a smash winner, the user clicks the UIStepper and it should 'add 1' onto the smash winners total and number of rallies, and also update the percentage which is the winner divided by the number of rallies. If there was a drop winner after, then drop winner total gets updated along with the number of rallies and the smash and drop winner percentages.
Hopefully I have explained it well enough for you guys to understand :/
I am using this bit of code to update a generic winner:
- (IBAction)netChanged:(id)sender {
self.netLabel.text = [NSString stringWithFormat:#"%d",
[[NSNumber numberWithDouble:[(UIStepper *)sender value]] intValue]];
float net = [self.netLabel.text floatValue];
float rally = [self.rallyLabel.text floatValue];
float netPercentage = (rally == 0.0) ? 0 : net / rally * 100;
self.netPercentageLabel.text = [NSString stringWithFormat:#"%.2f%%", netPercentage];
}
My question is, what do I need to do in terms of code to update other percentages and rallies played when there is a winner?
Thanks.
You should be saving that data somewhere else, and not in the text property of a UILabel. Update the values, and then update the labels to reflect the updated values.
I highly recommend re-reading the documentation on Model-View-Controller.
I have an NSArray in which I would like to store double values. I defined it as follow
NSMutableArray *setOfDoubles;
I add the elements as follow
NSNumber *num;
num = [NSNumber numberWithDouble:someDouble];
[setOfDoubles addObject:num];
And I read the element as follow
num = [setOfDoubles lastObject];
[setOfDoubles removeLastObject];
doubleValueToUse = [num doubleValue];
My problem is sometimes (Not always), for example when num (as an object) is 5.1, doubleValueToUse (as a double value) is 5.099999999999996. The way I figured num (as an object) is 5.1 is that I debug and when I am hovering the mouse on top of num on the line num = [setOfDoubles lastObject]; it shows 5.1 but after doubleValue conversion it becomes the number I mentioned. Does anybody know why is this happening?
Not every number can be accurately represented using a float variable. For example, you can't precisely represent, say, 1/3 using a finite number of digits in our common decimal (base-10) system, but in ternary (base-3), it would be just 0.1. Similarly, the numbers you can write with a finite number of digits in decimal, may not necessarily have the finite number of digits in their binary representation, hence the error.
A few links on the topic if you are interested:
http://floating-point-gui.de/basic/
http://www.mathworks.com/support/tech-notes/1100/1108.html
http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html
This is normal for float values.
If you want to save initial (same) representation of float numbers in all places of your code, you can save them, for example, in NSString. When you will need float number you will just write [NSString floatValue];. But it is not effective if you have large amount of float values.
I'm not quite sure what to call it, but I have a text field to hold a currency value, so I'm storing that as a NSDecimalNumber. I don't want to use the numbers & symbols keyboard so I'm using a number pad, and inferring the location of a decimal place like ATMs do. It works fine for entering numbers. Type 1234 and it displays $12.34 but now I need to implement back space. So assuming $12.34 is entered hitting back space would show $1.23. I'm not quite sure how to do this with a decimal number. With an int you would just divide by 10 to remove the right most digit, but that obviously doesn't work here. I could do it by some messy converting to int / 10 then back to decimal but that just sounds horrific... Any suggestions?
Call - (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber withBehavior:(id < NSDecimalNumberBehaviors >)behavior on it
How about using stringValue?
1) NSDecimalNumber to String
2) substring last
3) String to NSDecimalNumber
Below is an example for Swift 3
func popLastNumber(of number: NSDecimalNumber) -> NSDecimalNumber {
let stringFromNumber = number.stringValue //NSNumber property
let lastIndex = stringFromNumber.endIndex
let targetIndex = stringFromNumber.index(before: lastIndex)
let removed = stringFromNumber.substring(to: targetIndex)
return NSDecimalNumber(string: removed)
}
If your input number is a single digit, it would return NaN.
You could replace it to NSDecimalNumber.zero if you need.
It may works like delete button on calcultor.
It's not tested much.
If someone found another NaN case, please report by reply.
I have made a quadratic equation solver for the iPhone and when the text box is clicked, my own custom keypad appears. I have a button that changes whether the number is positive or negative. Right now I what happens is that when the button is pressed (0 - current value of text) is what is displayed in the text box, so if the number is positive, it will become negative and if it is negative it will become positive. I am having some problems doing this so what I wanted to is to put a minus sign at the beginning of the string if the number is positive and if the number is negative, the minus sign will be removed. Can anyone give me guidance on this?
Instead of negating using a mathematical function I assigned a NSMutableString to my UITextField then I inserted a "-" sign using insertString:atIndex: then I reassigned the changed string to my UITextField. To toggle between positive and negative, I created an if function so if the float value of my textfield is greater or equal to 0, then an "-" is inserted but if the float value of my text field is less than zero, the "-" is removed using deleteCharactersInRange. Here is my code as it stands:
- (IBAction)positivity{
NSMutableString *a = [NSMutableString stringWithString:aVal.text];
if([aVal.text floatValue]>=0){
[a insertString: #"-" atIndex: 0];
aVal.text = a;
}
else if([aVal.text floatValue]<0){
NSRange range = {0,1};
[a deleteCharactersInRange:range];
aVal.text = a;
}
}
aVal is the name of the UITextField that i am changing.
An alternative to the straight string approach is to not use a string. A while back I wrote a graphing calculator for iPhone that stored the equation internally in an NSMutableArray of NSStrings. Each slot in the array corresponded to one element in the equation, such as "x", "^", "sin(", etc.
When I needed to negate the equation, it was much easier to tell the array to insertObject:#"-" atIndex:0 than to try and insert it directly into the string. Then whenever the array was changed, I just remade the equation string like this:
NSString * newEquation = [equationElements componentsJoinedByString:#""];
While you could directly manipulate a string representation of a numeric value, such an approach is a bad idea. Not only is it less efficient than other alternatives, but potentially incorrect. (For example, #Ken's answer would result in two minus signs.)
What you probably want to do is negate the numeric value (just multiply it by -1, or subtract it from 0 as you suggested) and reflect that change in the interface (you mention a text box).
If you're using standard Cocoa controls (which inherit from NSControl, as NSTextField does) I suggest using -[NSControl setIntegerValue:] to change the text of the text field. If you (can) break up your UI well and have a text field for each variable in the quadratic equation, this should be fairly simple. (If you're using something other than an integer value, use something like -setDoubleValue: or -setFloatValue: instead.)
If you must create your own string beforehand, using an integer format specifier will display a "-" sign automatically if appropriate. Be sure to use %ld instead of %d (thanks, #Peter!) as the format specifier for NSInteger values to avoid possibly truncating values larger than 32-bit. For example:
NSString *result = [NSString stringWithFormat:#"%ld", nsIntegerValue];
In a more general sense, if you need to insert a dynamically-obtained string (not just something for which you can create a format string at compile time) you can also use an NSMutableString and its methods -appendString: and -insertString:atIndex: as well.