Find nearest float in array - ios

How would I get the nearest float in my array to a float of my choice? Here is my array:
[1.20, 1.50, 1.75, 1.95, 2.10]
For example, if my float was 1.60, I would like to produce the float 1.50.
Any ideas? Thanks in advance!

You can do it by sorting the array and finding the nearest one.
For this you can use sortDescriptors and then your algorithm will go.
Even you can loop through, by assuming first as the required value and store the minimum absolute (abs()) difference, if next difference is lesser than hold that value.
The working sample, however you need to handle other conditions like two similar values or your value is just between two value like 2 lies between 1 and 3.
NSArray *array = #[#1.20, #1.50, #1.75, #1.95, #2.10];
double my = 1.7;
NSNumber *nearest = array[0];
double diff = fabs(my - [array[0] doubleValue]);
for (NSNumber *num in array) {
double d = [num doubleValue];
if (diff > fabs(my - d) ) {
nearest = num;
diff = my - d;
}
}
NSLog(#"%#", nearest);

Related

Retrieve value from the Object

I have the following object which contains an array of NSDictionary. I wonder how could I able to get the sum of Quantity from this object.
In Objective-C there is a very convenient way using KVC Collection Operators:
NSNumber *sum = [sharedData.orderItems valueForKeyPath:#"#sum.Quantity.integerValue"];
NSInteger integerSum = sum.integerValue;
The other simple operators are:
#count - count of objects
#avg - average value
#max - maximum value
#min - minimum value
int sum=0;
for(NSDictionary *item in sharedData.orderitems){
sum = sum + [[item objectForKey:#"Quantity"] intValue];
}
NSLog(#"Sum = %d",sum);

Sort negative number string in iOS with NSStringCompareOptions

I am trying to sort some list of strings. And names of elements could be almost anything, from real names, strings, dates,... and numbers.
I found NSStringCompareOptions with NSNumericSearch, wich work fast enough and it work nice so :
[1,2,21,3,55,6] --> [1,2,3,6,21,55]
But my problems are negative numbers
[1,2,3,-1,-4,-5] --> [-1,-4,-5,1,2,3]
What it is not right.
I know that Apple stays :
Numeric comparison only applies to the numerals in the string,
not other characters that would have meaning in a numeric representation
such as a negative sign, a comma, or a decimal point.
But my question is how to achieve this, because I know I am not only who do this.
EDIT :
Thanks to Narendra Pandey, but my real case is a little bit complicated, so his answer can't be used here.
So let say I have some dictionary with numbers as keys and strings as values :
dic = {#1:#"123", #2:#"-123", #5:"MyName",...};
then I have array of object with ids.
array = #[{object with id 5}, {object with id 2},...];
and I need sorted array of object by name of properties.
NSStringCompareOptions comparisonOption = NSCaseInsensitiveSearch | NSNumericSearch;
array = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString * name1 = [dic objectForKey:obj1.someId];
NSString * name2 = [dic objectForKey:obj2.someId];
return [name1 compare:name2 options:comparisonOption];;
}];
EDIT 2:
Maybe I should state that I have solution, but it is 4 times slower that sorting with NSStringCompareOptions
// CHECK IF IT IS NUMBER
NSNumber * number1 = [numberFormatter numberFromString:string1];
NSNumber * number2 = [numberFormatter numberFromString:string2];
//
// NSLog(#"NUMBERS : %#, %#", number1, number2);
if (number1 && number2) {
return [number1 compare:number2];
}
return [string1 compare:string2 options:comparisonOption];
NSArray * numbers = #[#1, #2, #3, #-4, #-5, #6, #9];
NSPredicate * predicateForPositive = [NSPredicate predicateWithFormat:#"integerValue >= 0"];
NSArray * positiveNumbers = [numbers filteredArrayUsingPredicate:predicateForPositive];
NSPredicate * predicateForNegative = [NSPredicate predicateWithFormat:#"integerValue <= 0"];
NSArray * NegativeNumber = [numbers filteredArrayUsingPredicate:predicateForNegative];
NSLog(#"Negative number %#",NegativeNumber);
NSLog(#"Positive number %#",positiveNumbers);
Output:
Negative number (
"-4",
"-5"
)
Positive number (
1,
2,
3,
6,
9
)
Now sort both and concate both Array.
Thanks to Narendra Pandey I found solution for me.
Let me state first that Narendra Pandey solution works, but it is slower, even 3 times.
(in my case 0.014s with NSStringCompareOptions, and 0,042 Narendra Pandey solution).
But if I use his idea and change it a little bit :
array = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString * name1 = somehow get string1;
NSString * name2 = somehow get string2;
if ([string1 integerValue] <0 && [string2 integerValue]<0) {
return - [string1 compare:string2 options:comparisonOption];
}
return [string1 compare:string2 options:comparisonOption];
}];
this method is faster, in my case 0,015s which is comparable with NSStringCompareOptions.
In this way you avoid to go through whole array at beginning to separate negative and positive numbers, and then sort them.
This function get any array and convert it to sorted Double array
var numberArray: [Any] = [4, 3.9, -23,3, 7.6, -51, 75.3, "0", "-(22)"]
/// This function get any array and convert it to sorted _Double_ array
/// - Note: Non-numerical elements are automatically removed from the array
/// - Parameters:
/// - numbers: array of anything
/// - Returns: sorted _Double_ array
func sortAnyNumbers(_ numbers: [Any]) -> [Double] {
var _numbers: [Double] = []
numbers.forEach { number in
// Delete non-numeric characters
if let numb = Double("\(number)".components(separatedBy: CharacterSet(charactersIn: "-01234567890.").inverted).joined()) {
_numbers.append(numb)
}
}
return _numbers.sorted()
}
print(sortAnyNumbers(numberArray)) //[-51.0, -23.0, -22.0, 0.0, 3.0, 3.9, 4.0, 7.6, 75.3]

How to use complex number to plot an Argand Diagram?

I like to create an Argand Diagram from a set of complex number by using Objective-C.
Are there any solution or template that are available that can help me to do this?
Can anyone recommend an approach?
Similar youtube link is provided but it's an android program: https://www.youtube.com/watch?v=s0oTeZ12_ig
- (void)ComputeABCD
{
double designFrequency = 1e9;
double simulateFrequency = 1.5e9;
double pi = 3.14159265359;
double omega = 2*pi*simulateFrequency;
double thetarad=1;
complex double cascadedA=1+0*I;
complex double cascadedB=0+0*I;
complex double cascadedC=0+0*I;
complex double cascadedD=1+0*I;
complex double A=0+0*I;
complex double B=0+0*I;
complex double C=0+0*I;
complex double D=0+0*I;
complex double newA=0+0*I;
complex double newB=0+0*I;
complex double newC=0+0*I;
complex double newD=0+0*I;
int index=0;
for (id element in storeImpedance)
{
id element2 = [storeLength objectAtIndex:index];
id element3 = [storeIndex objectAtIndex:index];
NSNumber *numberImpedance = (NSNumber *)element;
double valueImpedance = [numberImpedance doubleValue];
NSNumber *numberLength = (NSNumber *)element2;
double valueLength = [numberLength doubleValue];
NSNumber *numberIndex = (NSNumber *)element3;
NSInteger valueIndex = [numberIndex integerValue];
++index;
if (valueIndex==0)
{
thetarad=valueLength*pi/180*simulateFrequency/designFrequency;
A=cos(thetarad);
B=I*valueImpedance*sin(thetarad);
C=I*sin(thetarad)/valueImpedance;
D=cos(thetarad);
}
if (valueIndex==1)
{
thetarad=valueLength*pi/180*simulateFrequency/designFrequency;
A=1;
B=0;
C=(I*tan(thetarad))/valueImpedance;
D=1;
}
newA=cascadedA*A+cascadedB*C;
newB=cascadedA*B+cascadedB*D;
newC=cascadedC*A+cascadedD*C;
newD=cascadedC*B+cascadedD*D;
cascadedA=newA;
cascadedB=newB;
cascadedC=newC;
cascadedD=newD;
}
printf("The MAT ABCD is:\n");
printf("%g + %gi\n", creal(cascadedA), cimag(cascadedA));
printf("%g + %gi\n", creal(cascadedB), cimag(cascadedB));
printf("%g + %gi\n", creal(cascadedC), cimag(cascadedC));
printf("%g + %gi\n", creal(cascadedD), cimag(cascadedD));
}

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.

Finding the nearest, lower number in a sorted NSArray

I have a sorted array of times like so
[0.0, 1.2, 4.3, 5.9, 7.2, 8.0]
While an audio file plays, I want to be able to take the current time and find what the nearest, lower number is in the array.
My approach would be to traverse the array, possible in reverse order as it feels like it should be faster. Is there a better way?
The playback SHOULD be linear, but might be fast-forwarded/rewound, so I would like to come up with a solution that takes that into account, but I'm not really sure how else to approach the problem.
The method you are looking for is -[NSArray indexOfObject:inSortedRange:options:usingComparator:]. It performs a binary search. With the options:NSBinarySearchingInsertionIndex option, if the value isn't found exactly, it returns the index where the object would be inserted, which is the index of the least larger element, or the count of items in the array.
NSTimeInterval currentTime = ...;
NSUInteger index = [times indexOfObject:#(currentTime)
inSortedRange:NSMakeRange(0, times.count)
options:NSBinarySearchingInsertionIndex
usingComparator:^(id object0, id object1) {
NSTimeInterval time0 = [object0 doubleValue];
NSTimeInterval time1 = [object1 doubleValue];
if (time0 < time1) return NSOrderedAscending;
else if (time0 > time1) return NSOrderedDescending;
else return NSOrderedSame;
}];
// If currentTime was not found exactly, then index is the next larger element
// or array count..
if (index == times.count || [times[index] doubleValue] > currentTime) {
--index;
}
The fastest* way to find something in a sorted array is binary search: if there are n items, check the element at index n/2. If that element is greater than what you're looking for, check the element at index n/4; otherwise, if it's less than what you're looking for, check the element at index 3n/4. Continue subdividing in this fashion until you've found what you want, i.e. the position where the current time should be. Then you can pick the preceding element, as that's the closest element that's less than the current time.
However, once you've done that once, you can keep track of where you are in the list. As the user plays through the file, keep checking to see if the time has passed the next element and so on. In other words, remember where you were, and use that when you check again. If the user rewinds, check the preceding elements.
*Arguably, this isn't strictly true -- there are surely faster ways if you can make a good guess as to the probable location of the element in question. But if you don't know anything other than that the element appears somewhere in the array, it's usually the right approach.
I'm not sure if it's the best approach, but I think it'll get the job done (assuming your array is always ascending order).
- (NSNumber *) incrementalClosestLowestNumberForNumber:(NSNumber *)aNumber inArray:(NSArray *)array {
for (int i = 0; i < array.count; i++) {
if ([array[i] floatValue] == [aNumber floatValue]) {
return aNumber;
}
else if ([array[i] floatValue] > [aNumber floatValue]) {
int index = (i > 0) ? i - 1 : 0;
return array[index];
}
}
return #0;
}
Then call it like this:
NSArray * numbArray = #[#0.0, #1.2, #4.3, #5.9, #7.2, #8.0];
NSNumber * closestNumber = [self closestLowestNumberForNumber:#2.4 inArray:numbArray];
NSLog(#"closest number: %#", closestNumber);
I'm not sure if someone else knows a special way that is much faster.
Based on some of the other answers / comments, I came up with this, perhaps one of them can point out if a whole is somewhere.
- (NSNumber *) quartalClosestLowestNumberForNumber:(NSNumber *)compareNumber inArray:(NSArray *)array {
int low = 0;
int high = array.count - 1;
NSNumber * lastNumber;
int currentIndex = 0;
for (currentIndex = low + (high - low) / 2; low <= high; currentIndex = low + (high - low) / 2) {
NSNumber * numb = array[currentIndex];
if (numb.floatValue < compareNumber.floatValue) {
low = currentIndex + 1;
}
else if (numb.floatValue > compareNumber.floatValue) {
high = currentIndex - 1;
}
else if (numb.floatValue == compareNumber.floatValue) {
return numb;
}
lastNumber = numb;
}
if (lastNumber.floatValue > compareNumber.floatValue && currentIndex != 0) {
lastNumber = array[currentIndex - 1];
}
return lastNumber;
}
I'm really bored right now, so I'm trying to test the fastest method. Here's how I did it.
NSMutableArray * numbersArray = [NSMutableArray new];
for (int i = 0; i < 100000; i++) {
float floater = i / 100.0;
[numbersArray addObject: #(floater)];
}
// courtesy #RobMayoff
NSDate * binaryDate = [NSDate date];
NSNumber * closestNumberBinary = [self binaryClosestLowestNumberForNumber:#4.4 inArray:numbersArray];
NSLog(#"Found closest number binary: %# in: %f seconds", closestNumberBinary, -[binaryDate timeIntervalSinceNow]);
// The Quartal Version
NSDate * quartalDate = [NSDate date];
NSNumber * closestNumberQuartal = [self quartalClosestLowestNumberForNumber:#4.4 inArray:numbersArray];
NSLog(#"Found closest number quartal: %# in: %f seconds", closestNumberQuartal, -[quartalDate timeIntervalSinceNow]);
// The incremental version
NSDate * incrementalDate = [NSDate date];
NSNumber * closestNumberIncremental = [self incrementalClosestLowestNumberForNumber:#4.4 inArray:numbersArray];
NSLog(#"Found closest number incremental: %# in: %f seconds", closestNumberIncremental, -[incrementalDate timeIntervalSinceNow]);
And here's the output:
Found closest number binary: 4.4 in: 0.000030 seconds
Found closest number quartal: 4.4 in: 0.000015 seconds
Found closest number incremental: 4.4 in: 0.000092 seconds
And another test case:
Found closest number binary: 751.48 in: 0.000030 seconds
Found closest number quartal: 751.48 in: 0.000016 seconds
Found closest number incremental: 751.48 in: 0.013042 seconds

Resources