Return same double only if the double is an int? (no decimals) Obj-C - objective-c

I'm using a for-loop to determine whether the long double is an int. I have it set up that the for loop loops another long double that is between 2 and final^1/2. Final is a loop I have set up that is basically 2 to the power of 2-10 minus 1. I am then checking if final is an integer. My question is how can I get only the final values that are integers?
My explanation may have been a bit confusing so here is my entire loop code. BTW I am using long doubles because I plan on increasing these numbers very largely.
for (long double ld = 1; ld<10; ld++) {
long double final = powl(2, ld) - 1;
//Would return e.g. 1, 3, 7, 15, 31, 63...etc.
for (long double pD = 2; pD <= powl(final, 0.5); pD++) {
//Create new long double
long double newFinal = final / pD;
//Check if new long double is int
long int intPart = (long int)newFinal;
long double newLong = newFinal - intPart;
if (newLong == 0) {
NSLog(#"Integer");
//Return only the final ints?
}
}
}

Just cast it to an int and subtract it from itself?
long double d;
//assign a value to d
int i = (int)d;
if((double)(d - i) == 0) {
//d has no fractional part
}
As a note... because of the way floating point math works in programming, this == check isn't necessarily the best thing to do. Better would be to decide on a certain level of tolerance, and check whether d was within that tolerance.
For example:
if(fabs((double)(d - i)) < 0.000001) {
//d's fractional part is close enough to 0 for your purposes
}
You can also use long long int and long double to accomplish the same thing. Just be sure you're using the right absolute value function for whatever type you're using:
fabsf(float)
fabs(double)
fabsl(long double)
EDIT... Based on clarification of the actual problem... it seems you're just trying to figure out how to return a collection from a method.
-(NSMutableArray*)yourMethodName {
NSMutableArray *retnArr = [NSMutableArray array];
for(/*some loop logic*/) {
// logic to determine if the number is an int
if(/*number is an int*/) {
[retnArr addObject:[NSNumber numberWithInt:/*current number*/]];
}
}
return retnArr;
}
Stick your logic into this method. Once you've found a number you want to return, stick it into the array using the [retnArr addObject:[NSNumber numberWithInt:]]; method I put up there.
Once you've returned the array, access the numbers like this:
[[arrReturnedFromMethod objectAtIndex:someIndex] intValue];
Optionally, you might want to throw them into the NSNumber object as different types.
You can also use:
[NSNumber numberWithDouble:]
[NSNumber numberWithLongLong:]
And there are matching getters (doubleValue,longLongValue) to extract the number. There are lots of other methods for NSNumber, but these seem the most likely you'd want to be using.

Related

array lists in java: exclude the first element from `for` loop

I am taking an introduction to Java programing class and I have an array list where I need to exclude the first element from my for loop that finds an average. The first element in the array list is a weight for the average (which is why it needs to be excluded). I also need to drop the lowest value from the remainder of the array list hence my second for loop. I have tried to create a copy of the list and also tried to create a sub list but I cannot get it to work.
public static double Avgerage(ArrayList<Double> inputValues) {
double avg;
double sum = 0;
double weightValue = inputValues.get(0);
double lowest = inputValues.get(0);
for (int i = 1; i > inputValues.size(); i++) {
if (inputValues.get(i) < lowest) {
lowest = inputValues.get(i);
}
}
for (int i = 0; i < inputValues.size(); i++) {
sum = sum + inputValues.get(i);
}
double average = (sum - lowest) / (inputValues.size() - 1);
avg = average * weightValue;
return avg;
}
To start with good programming practice, you should work with interfaces rather than classes, where possible. The appropriate interface here is List<Double>, and when you create it in your class, you should use
List<Double> nameOfList = new ArrayList<Double>();
What we're doing is creating an object which has the behaviour of a List, with the underlying implementation of an ArrayList (more info here.
With regards to the question, you don't appear to be excluding the first element, as you said you wished to - both for loops iterate through all values in the list. Remember to treat the ArrayList like an array - accessing an element does not modify it, like it might in a Queue.
I have edited your code below to demonstrate this, and have also included some other optimisations and corrected the sign error on line 7:
public static double average(List<Double> inputValues) {
double sum = 0;
//Exclude the first element, as it contains the weight
double lowest = inputValues.get(1);
for (int i = 2; i < inputValues.size(); i++) {
lowest = Math.min(inputValues.get(i), lowest);
}
for (int i = 1; i < inputValues.size(); i++) {
sum += inputValues.get(i);
}
double average = (sum - lowest) / (inputValues.size() - 1);
//Scale by the weight
avg *= inputValues.get(0);
return avg;
}
Note: The convention in java is to use camelCase for method names, I have adjusted accordingly.
Also, I don't know your requirements, but optimally, you should be providing logical parameters. If possible do the following before calling the function:
int weight = inputValues.get(0);
inputValues.remove(0);
//And then you would call like this, and update your method signature to match
average(inputValues, weight);
I don't do this inside the method, as the context implies that we would not be modifying values.

Something weird in for loop speed

here is a part of my program code:
int test;
for(uint i = 0; i < 1700; i++) {
test++;
}
the whole program takes 0.5 seconds to finish, but when I change it to:
int test[1];
for(uint i = 0; i < 1700; i++) {
test[0]++;
}
it will takes 3.5 seconds! and when I change the int to double, it will gets very worse:
double test;
for(uint i = 0; i < 1700; i++) {
test++;
}
it will takes about 18 seconds to finish !!!
I have to increase an int array element and a double variable in my real for loop, and it will takes about 30 seconds!
What's happening here?! Why should it takes that much time for just an increment?!
I know a floating point data type like double has different structure from a fixed point data type like int, but is it the only cause for such a big different time? and what about the second example which is also an int array element?!
Thanks
You have answered your question yourself.
float (double) operations are different from integer ones. Even if you just add 1.0f.
Your second example takes longer than the first one just because you added some pointer refernces. An array in C is -bottom down- not much different from a pointer to the first element. Accessing any element, even the first one, would cause the machine code to load the starting address of the array multiply the index (0 in this case) with the length of each member (4 or whatever bytes int has) and add that (0) to the pointer. Then it has to dereference the pointer, meaning to acutally load the value at that very address. Add one and write back the result.
A smart modern compiler should optimize this a bit. When you want to avoid this optimization, then modify the code a bit and don`t use a constant for the index.
I never tried that with a modern objective-c compiler. But I guess that this code would take much loger than 3.5s to run:
int test[2];
int index = 0;
for(uint i = 0; i < 1700; i++) {
test[index]++;
}
If that does not make much of a change then try this:
-(void)foo:(int)index {
int test[2];
for(uint i = 0; i < 1700; i++) {
test[index]++;
}
}
and then call foo:0;
Give it a try and let us know :)

NSDecimalNumber to the power of NSDecimalNumber

I have two NSDecimalNumbers and I need to apply one to the power of the other, originally this code was using doubles and I could compute this with the pow() function like this:
double result = pow(value1, value2);
The problem I have is I am converting the code to use NSDecimalNumbers and although they include the method toThePowerOf, it only accepts int values. At the moment the only solution I have to this problem is to convert the NSDecimalNumbers Temporarily but this results in a loss of precision.
double value1 = [decimal1 doubleValue];
double value2 = [decimal2 doubleValue];
double result = pow(value1, value2);
NSDecimalNumber *decimalResult = [[NSDecimalNumber alloc] initWithDouble:result];
Is there a way I can do this computation with NSDecimalNumbers and not lose the precision?
I need this to work with non integer values for example:
value1 = 1.06
value2 = 0.0277777777
As Joe points out, if you want to do this for positive integer powers, you can use NSDecimalPower() on an NSDecimal struct derived from your NSDecimalNumber (I personally prefer working with the structs, for performance reasons).
For the more general case of working with negative integers and fractional values, I have some code that I've modified from Dave DeLong's DDMathParser library. He has since removed the NSDecimal portion of this library, but you can find the last commit for this support. I extended Dave's exponential support into the following 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;
}
This runs exact calculations on positive integer powers, negative integer powers, and fractional powers that map directly to roots. It still falls back on floating point calculations for fractional powers that don't cleanly fall into one of those bins, though.
Unfortunately, this requires a few of his other supporting functions to work. Therefore, I've uploaded my enhanced versions of his _DDDecimalFunctions.h and _DDDecimalFunctions.m that provide this functionality. They also include NSDecimal trigonometry, logarithm, and a few other functions. There are currently some issues with convergence on the tangent implementation, which is why I haven't finished a public post about this.
I came across the same problem recently and developed my own function to do exactly this. The function has will calculate any base to any power as long as it yields a real answer if it determines a real answer cannot be calculated it returns NSDecimalnumber.notANumber
I have posted my solution as an answer to the same question that I posted so here is the link.

NSString constrainedToSize method?

Not to get confused with the NSString sizeWithFont method that returns a CGSize, what I'm looking for is a method that returns an NSString constrained to a certain CGSize. The reason I want to do this is so that when drawing text with Core Text, I can get append an ellipses (...) to the end of the string. I know NSString's drawInRect method does this for me, but I'm using Core Text, and kCTLineBreakByTruncatingTail truncates the end of each line rather than the end of the string.
There's this method that I found that truncates a string to a certain width, and it's not that hard to change it to make it work for a CGSize, but the algorithm is unbelievably slow for long strings, and is practically unusable. (It took over 10 seconds to truncate a long string). There has to be a more "computer science"/mathematical algorithm way to do this faster. Anyone daring enough to try to come up with a faster implementation?
Edit: I've managed to make this in to a binary algorithm:
-(NSString*)getStringByTruncatingToSize:(CGSize)size string:(NSString*)string withFont:(UIFont*)font
{
int min = 0, max = string.length, mid;
while (min < max) {
mid = (min+max)/2;
NSString *currentString = [string substringWithRange:NSMakeRange(min, mid - min)];
CGSize currentSize = [currentString sizeWithFont:font constrainedToSize:CGSizeMake(size.width, MAXFLOAT)];
if (currentSize.height < size.height){
min = mid + 1;
} else if (currentSize.height > size.height) {
max = mid - 1;
} else {
break;
}
}
NSMutableString *finalString = [[string substringWithRange:NSMakeRange(0, min)] mutableCopy];
if(finalString.length < self.length)
[finalString replaceCharactersInRange:NSMakeRange(finalString.length - 3, 3) withString:#"..."];
return finalString;
}
The problem is that this sometimes cuts the string too short when it has room to spare. I think this is where that last condition comes in to play. How do I make sure it doesn't cut off too much?
Good news! There is a "computer science/mathematical way" to do this faster.
The example you link to does a linear search: it just chops one character at a time from the end of the string until it's short enough. So, the amount of time it takes will scale linearly with the length of the string, and with long strings it will be really slow, as you've discovered.
However, you can easily apply a binary search technique to the string. Instead of starting at the end and dropping off one character at a time, you start in the middle:
THIS IS THE STRING THAT YOU WANT TO TRUNCATE
^
You compute the width of "THIS IS THE STRING THAT". If it is too wide, you move your test point to the midpoint of the space on the left. Like this:
THIS IS THE STRING THAT YOU WANT TO TRUNCATE
^ |
On the other hand, if it isn't wide enough, you move the test point to the midpoint of the other half:
THIS IS THE STRING THAT YOU WANT TO TRUNCATE
| ^
You repeat this until you find the point that is just under your width limit. Because you're dividing your search area in half each time, you'll never need to compute the width more than log2 N times (where N is the length of the string) which doesn't grow very fast, even for very long strings.
To put it another way, if you double the length of your input string, that's only one additional width computation.
Starting with Wikipedia's binary search sample, here's an example. Note that since we're not looking for an exact match (you want largest that will fit) the logic is slightly different.
int binary_search(NSString *A, float max_width, int imin, int imax)
{
// continue searching while [imin,imax] is not empty
while (imax >= imin)
{
/* calculate the midpoint for roughly equal partition */
int imid = (imin + imax) / 2;
// determine which subarray to search
float width = ComputeWidthOfString([A substringToIndex:imid]);
if (width < max_width)
// change min index to search upper subarray
imin = imid + 1;
else if (width > max_width )
// change max index to search lower subarray
imax = imid - 1;
else
// exact match found at index imid
return imid;
}
// Normally, this is the "not found" case, but we're just looking for
// the best fit, so we return something here.
return imin;
}
You need to do some math or testing to figure out what's the right index at the bottom, but it's definitely imin or imax, plus or minus one.

Rounding with significant digits

In Xcode /Objective-C for the iPhone.
I have a float with the value 0.00004876544. How would I get it to display to two decimal places after the first significant number?
For example, 0.00004876544 would read 0.000049.
I didn't run this through a compiler to double-check it, but here's the basic jist of the algorithm (converted from the answer to this question):
-(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;
}
The important thing to remember is that Objective-C is a superset of C, so anything that is valid in C is also valid in Objective-C. This method uses C functions defined in math.h.