Check number of digits - ios

This may be simple answer... What is the quickest algorithm to check if a number contains more than four digits? I am trying to create an if-then statement. If number x contains more than 4 digits, then...

So, I'm not sure if this is really as super basic as it sounds or not, but here's a couple of thoughts that might help:
Assuming it's an integer, can you simply test for it being 10,000 or greater (or -10,000 or less)?
if (abs(numberToTest) > 9999) {
// Number has 4 or more digits
} else {
// Number has 3 or fewer digits
}
Alternatively, if you're dealing with decimal values, you could try this:
NSString *stringToTest = [NSString stringWithFormat:#"%f", numberToTest];
// If you want to exclude the decimal place from the calculation
stringToTest = [stringToTest stringByReplacingOccurrencesOfString:#"."
withString:#""];
// If you want to include a negative sign from the calculation
stringToTest = [stringToTest stringByReplacingOccurrencesOfString:#"-"
withString:#""];
if (stringToTest.length > 4) {
// String has 5 or more digits
} else {
// String has 4 or fewer digits
}
Anyway, you didn't give a ton of detail, but maybe this solves your problem.

if its an int you could just subtract the number minus 9999 and determine if the result is negitive or positive but i assume its more complex than this

Yes you could just use an if statement
if (number > 9999)
print" we are in the 10000 range";
else
print " we are in less than 10000";

Is one line short enough?
let moreThanFourDigits = String(yourNumber).count > 4
Here I simply transform the number into a string and count the characters.

Related

get int value including zeros (incase if it starts with 0) from string

I have a question regarding the converting string to intvalue. My question and issue is in case if I have string called "001223" I am getting 1223 as intvalue. But I want to get the 001223 as final int value. Please let me know if my question is not clear. Thanks for your time
There is no difference in value between the numbers 001223 , 1223, 2446/2 or 1223.000. They all refer to the same number.
If you want to keep leading zeroes, then you need to either keep it as a string or maintain another piece of information so it can be rebuilt later, basically the number of zeroes at the front, such as:
struct sNumWithLeadingZeros {
size_t zeroCount;
unsigned int actualValue;
};
I'd probably suggest the former (keeping it as a string) since that's likely to be less effort.
"Leading zeros" are to do with the textual representation of an integer, when stored as integer values in a computer the leading zeros do not exist.
However, if what you want to do is display the number with the same number of digits it had before being converted from text then: if the string contains only the digits of the number, e.g. you have #"001223" then you can take the length of this string to determine the number of digits. Later when converting the number back to string format you can use a formatted conversion, e.g. stringWithFormat:, and a format specifier which specifies the required number of digits. You'll need to read up on formats in the documentation, but here is an example:
NSString *input = #"001223";
int x = [input intValue];
int digits = (int)input.length;
NSString *output = [NSString stringWithFormat:#"%0*d", digits, x];
The value of output will be the same as input. The format broken down is: 0 - leading zeros; * use a dynamic field with, will use the value of digits; d - int.
HTH
One cannot prefix leading 0s in int data type. But if you see 0 prefix then the number is octal not decimal. Octal value can be created by changing base. For this you can use wrapper class like Integer.
But if one wants leading 0s for displaying data then he/she can use following code
public class Sample
{
public static void main(final String[] argv)
{
System.out.printf("%06d", 1223);
System.out.println();
}
}

how does the pow function work?

I am looking to write my own power function to work with NSDecimalNumbers and exponents that are not whole numbers. I first tried to use a combination of newtons method and the built in integer power method, but due to newtons method i am getting overflow errors when I have exponents with more than 2 decimals. So I thought maybe the float value pow function might serve as a good model for my own function. So I was wondering if anyone knows where I can fond some sort of documentation on the inner workings of the pow function?
Edit:
#wombat57, those links look like they could be what I am looking for however I have no idea to read them. The algorithm you suggest is in fact what I am using. the overflow comes from newtons method due to very large exponents. Because I am getting exponents in decimal form I have to convert it to a fraction first. the only way of ding this in code, as far as I know, multiplying the decimal by ten until you have a whole number, and using that as the numerator. Doing this you get exponents of 100+ for numbers with 3 or more decimals. this causes an overflow error.
EDIT 1: Here are links to the actual source
http://opensource.apple.com/source/Libm/Libm-2026/Source/Intel/expf_logf_powf.c
http://opensource.apple.com/source/Libm/Libm-315/Source/ARM/powf.c
I got the links from this question, which has a bunch of relevant discussion
self made pow() c++
This page describes an algorithm: Link.
x^(1/n) = the nth root of x, and x^mn = (x^m)^n. Thus, x^(m/n) = (the nth root of x)^m. Arbitrary roots can be calculated with Newton's method. Integer powers can be calculated with Exponentiation by squaring. For irrational exponents, you can use increasingly accurate rational approximations until you get the desired number of significant digits.
EDIT 2:
Newton's method involves raising your current guess to the power of the root that you're trying to find. If that power is large, and the guess is even a little too high, this can result in overflow. One solution here is to identify this case. If overflow ever occurs, this means that the guess was too high. You can solve the problem by (whenever a guess results in overflow), setting the current guess to a value between the last guess that did not overflow and the current guess (you may have to do this several times). That is, whenever Newton's method overflows, do a binary search down toward the last guess that did not overflow. Here's some python that implements all of this:
def nroot(n, b, sig_figs = 10):
g1 = 1.0
g2 = 1.0
while True:
done = False
while not done:
try:
g3 = g2 - ((g2**b) - n) / (b * (g2**(b-1)))
done = True
except OverflowError:
g2 = (g1 + g2) / 2.0
if abs(g2 - g3) < 1.0 / (10**sig_figs):
return g3
g1 = g2
g2 = g3
def npowbysqr(n, p):
if p == 0:
return 1.0
if p % 2 == 0:
v = npowbysqr(n, p/2)
return v*v
else:
return n*npowbysqr(n, p-1)
def npow(n, p):
return npowbysqr(nroot(n, 1000000), int(p*1000000))
print npow(5, 4.3467)
print 5**4.3467
I should add that there are probably much better solutions. This does seem to work, however
I happened to need something like this a while ago. Thankfully, Dave DeLong had been tinkering with this in his DDMathParser, so I built off of that. He yanked his implementation from his code in this commit, but I took that and modified it. This is my version of his NSDecimal power function:
extern NSDecimal DDDecimalPower(NSDecimal d, NSDecimal power) {
NSDecimal r = DDDecimalOne();
NSDecimal zero = DDDecimalZero();
NSComparisonResult compareToZero = NSDecimalCompare(&zero, &power);
if (compareToZero == NSOrderedSame) {
return r;
}
if (DDDecimalIsInteger(power))
{
if (compareToZero == NSOrderedAscending)
{
// we can only use the NSDecimal function for positive integers
NSUInteger p = DDUIntegerFromDecimal(power);
NSDecimalPower(&r, &d, p, NSRoundBankers);
}
else
{
// For negative integers, we can take the inverse of the positive root
NSUInteger p = DDUIntegerFromDecimal(power);
p = -p;
NSDecimalPower(&r, &d, p, NSRoundBankers);
r = DDDecimalInverse(r);
}
} else {
// Check whether this is the inverse of an integer
NSDecimal inversePower = DDDecimalInverse(power);
NSDecimalRound(&inversePower, &inversePower, 34, NSRoundBankers); // Round to 34 digits to deal with cases like 1/3
if (DDDecimalIsInteger(inversePower))
{
r = DDDecimalNthRoot(d, inversePower);
}
else
{
double base = DDDoubleFromDecimal(d);
double p = DDDoubleFromDecimal(power);
double result = pow(base, p);
r = DDDecimalFromDouble(result);
}
}
return r;
}
It tries to identify common cases and use more precise calculations for those. It does fall back on pow() for things that don't fit in these cases, though.
The rest of the NSDecimal functions I use can be found here and here.
I have come up with a function that suits my needs and will hopefully suit the needs of many others. the following method is fully annotated and works for any power function that has a real value. This method also only uses NSDecimalNumbers meaning you will not loose any precision due to float rounding error. This method takes two arguments one for the base and one for the power, and both are NSDecimalNumbers. So here it is:
//these are constants that will be used
NSDecimalNumber *ten = [NSDecimalNumber decimalNumberWithString:#"10"];
NSDecimalNumber *one = NSDecimalNumber.one;
//these will together hold the power in fractional form
NSDecimalNumber *numerator = power, *denominator = one;
//this will hold the final answer and all previous guesses the first guess is set to be the base
NSDecimalNumber *powAns = base;
//this will hold the change in your guess, also serves as an idea of how large the error is
NSDecimalNumber *error = one;
//part1 holds f(x) and part2 holds f'(x)
NSDecimalNumber *part1, *part2;
//if the base is < 0 and the power is not whole, answer is not real
if ([base doubleValue] < 0 && [[power stringValue] rangeOfString:#"."].location != NSNotFound)
return NSDecimalNumber.notANumber;
//converts power to a fractional value
while ([[numerator stringValue] rangeOfString:#"."].location != NSNotFound) {
numerator = [numerator decimalNumberByMultiplyingBy:ten];
denominator = [denominator decimalNumberByMultiplyingBy:ten];
}
//conditions here are the precision you wish to get
while ([error compare:[NSDecimalNumber decimalNumberWithString:#"1e-20"]] == NSOrderedDescending ||
[error compare:[NSDecimalNumber decimalNumberWithString:#"-1e-20"]] == NSOrderedAscending) {
//if this catches an overflow error it is set to be a very large number otherwise the value cannot be a number, however no other error should be returned.
#try {
part1 = [powAns decimalNumberByRaisingToPower:[denominator intValue]];
}
#catch (NSException *exception) {
if ([exception.name isEqual: NSDecimalNumberOverflowException])
part1 = [NSDecimalNumber decimalNumberWithString:#"10e127"];
else
return NSDecimalNumber.notANumber;
}
part1 = [part1 decimalNumberBySubtracting:base];
//if this catches an overflow error it is set to be a very large number otherwise the value cannot be a number, however no other error should be returned.
#try {
part2 = [powAns decimalNumberByRaisingToPower:[denominator intValue]-1];
part2 = [part2 decimalNumberByMultiplyingBy:denominator];
}
#catch (NSException *exception) {
if ([exception.name isEqual: NSDecimalNumberOverflowException])
part2 = [NSDecimalNumber decimalNumberWithString:#"10e127"];
else
return NSDecimalNumber.notANumber;
}
//error is the change in the estimated value or y - f(x)/f'(x)
error = [part1 decimalNumberByDividingBy:part2];
powAns = [powAns decimalNumberBySubtracting: error];
}
//if the numerator value is negative it must be made positive and the answer is then inverted
if ([numerator intValue] < 0) {
powAns = [powAns decimalNumberByRaisingToPower:abs([numerator intValue])];
powAns = [one decimalNumberByDividingBy:powAns];
}
else
powAns = [powAns decimalNumberByRaisingToPower:[numerator intValue]];
return powAns;
If anyone has any questions about my code I am happy to answer them.

How can I count decimal digits?

I have to count how many decimal digits are there in a double in Xcode 5. I know that I must convert my double in a NSString, but can you explain me how could I exactly do? Thanks
A significant problem is that a double has a fractional part which has no defined length. If you know you want, say, 3 fractional digits, you could do:
[[NSString stringWithFormat:#"%1.3f", theDoubleNumber] length]
There are more elegant ways, using modulo arithmetic or logarithms, but how elegant do you want to be?
A good method could be to take your double value and, for each iteration, increment a counter, multiply your value by ten, and constantly check if the left decimal part is really near from zero.
This could be a solution (referring to a previous code made by Graham Perks):
int countDigits(double num) {
int rv = 0;
const double insignificantDigit = 8;
double intpart, fracpart;
fracpart = modf(num, &intpart);
while ((fabs(fracpart) > 0.000000001f) && (rv < insignificantDigit))
{
num *= 10;
fracpart = modf(num, &intpart);
rv++;
}
return rv;
}
You could wrap the double in an instance of NSNumber and get an NSString representation from the NSNumber instance. From there, calculating the number of digits after the decimal could be done.
One possible way would be to implement a method that takes a double as an argument and returns an integer that represents the number of decimal places -
- (NSUInteger)decimalPlacesForDouble:(double)number {
// wrap double value in an instance of NSNumber
NSNumber *num = [NSNumber numberWithDouble:number];
// next make it a string
NSString *resultString = [num stringValue];
NSLog(#"result string is %#",resultString);
// scan to find how many chars we're not interested in
NSScanner *theScanner = [NSScanner scannerWithString:resultString];
NSString *decimalPoint = #".";
NSString *unwanted = nil;
[theScanner scanUpToString:decimalPoint intoString:&unwanted];
NSLog(#"unwanted is %#", unwanted);
// the number of decimals will be string length - unwanted length - 1
NSUInteger numDecimalPlaces = (([resultString length] - [unwanted length]) > 0) ? [resultString length] - [unwanted length] - 1 : 0;
return numDecimalPlaces;
}
Test the method with some code like this -
// test by changing double value here...
double testDouble = 1876.9999999999;
NSLog(#"number of decimals is %lu", (unsigned long)[self decimalPlacesForDouble:testDouble]);
results -
result string is 1876.9999999999
unwanted is 1876
number of decimals is 10
Depending on the value of the double, NSNumber may do some 'rounding trickery' so this method may or may not suit your requirements. It should be tested first with an approximate range of values that your implementation expects to determine if this approach is appropriate.

Check to see if UITextField has a numeric value greater than 0

I have a UITextField and I only want a number greater than 0 ( I don't want non-numeric characters or the value 0 )
This is how I check to see if it is empty:
if(seizure.text.length==0)
This is how I check to see if it is equal to 0:
else if(seizure.text doubleValue]==0)
How can I check for non-numeric characters?
First check to see if you have any characters in the string, then check to make sure that it only contains numeric characters, and finally check to see if the value is greater than 0:
if (seizure.text.length > 0)
{
NSCharacterSet *nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([seizure.text rangeOfCharacterFromSet:nonNumbers].location == NSNotFound)
{
if ([seizure.text doubleValue] > 0)
{
// Text Field contains a numeric value greater than 0
NSLog(#"Good number.");
return;
}
}
}
// If we make it to here, it does not meet your requirements.
NSLog(#"Bad Number.");
NSScanner will do the job nicely here. Unlike -[NSString doubleValue], its scanDouble: can parse and then also tell you whether it consumed the entire string, so you will know that there are non-numerical characters present.
Demonstration on some test cases. See the comments for descriptions of the expected results.
NSArray * texts = #[// First four unacceptable because non-numeric
#"", #"Hello, world!", #"1.0 excelsior", #"Jiminy 1.0 Crickets",
// These three unacceptable because 0 or less
#"0.0" #"0", #"-2048",
// Last three are good
#"3.14159", #"1", #"10000000000.0"];
for( NSString * text in texts ){
NSScanner * scanner = [NSScanner scannerWithString:text];
double val;
[scanner scanDouble:&val];
// Scanned the whole string and ended up with a positive value
if( [scanner isAtEnd] && val > 0 ){
NSLog(#"'%#'? I accept.", text);
}
else {
NSLog(#"'%#' is no good.", text);
}
}
[seizure.text doubleValue] == 0 will be true either if seizure.text is a textual representation of zero or if it doesn't contain a valid textual representation of a number (see the documentation for doubleValue).
In other words if this expression is false then you have a string value which starts with a number. However you still don't know if you string value contains only a number, e.g. [#"2.5 miles" doubleValue] has the value 2.5. If you need to handle strings like this you should look at NSScanner.

iOS - %G float can only handle six numbers

Why does the %g format for strings only handle six numbers in a float and after that it turns into scientific notation? Is there any other way of displaying a float with something similar to the %g format but allows more than six numbers?
EDIT: I have figured out %g with precision i.e turning %g into %.Xg where x is the specified number of significant digits. But it doesnt help me in this situation:
-(IBAction)numberPressed:(id)sender {
if (decimalChecker == 1) {
currentDecimal = currentDecimal*10+ (float)[sender tag];
decimaledNumberString = [[NSString alloc] initWithFormat:#"%.17g.%.17g", currentNumber, currentDecimal];
calculatorScreen.text = decimaledNumberString;
currentDecimaledNumber = [decimaledNumberString floatValue];
NSLog(#"regular");
} else {
currentNumber = currentNumber*10+ (float)[sender tag];
calculatorScreen.text = [[NSString alloc] initWithFormat:#"%.17g", currentNumber];
NSLog(#"regular");
}
}
If I press "5" eight times instead of 55555555, I get 55551782 or something similar. How can I fix it to where I get the desired eight fives instead of the crazy number?
Insert a period and a numeral to specify the maximum number of significant digits you would like displayed, such as %.17g for 17 significant digits. As you discovered, the default is six.
According to http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Strings/Articles/FormatStrings.html#//apple_ref/doc/uid/20000943, iOS string formatting uses the same placeholders as C's printf(), which specifies g/G as representing FP values with exponential notation for very large/small values while f only uses non-exponential representation.
http://en.wikipedia.org/wiki/Printf_format_string#Format_placeholders

Resources