Reverse a double value - objective-c

I'm trying to reverse a double value like this:
Input: 1020304050...... Output: 5040302010
the group of 2 digits remain in the same order. So 10 doesn't become 01. or 53 doesn't become 35.
The input will always have even number of digits, so pairing isn't an issue.
The 2 adjacent digits are actually a code number for a function. And I want to maintain that so I can apply that function again.
double temp = 0.0;
double Singlefilter=1;
double reverseString=0;
temp=filtersequence;
while (temp>0)
{
Singlefilter=fmod(temp, 100.00);
temp=temp/100;
reverseString=(reverseString+Singlefilter)*100;
NSLog(#"reversed string of filter %f",reverseString);
}
But I have no idea why this isn't working. This is generating randomly very very big values.
[This question has been replaced by Reverse a double value while maintaining 2 adjacent digits in same format]

You can do it like this:
#import <Foundation/Foundation.h>
#include "math.h"
void outputGroupReversed(double filtersequence)
{
double reverseString = 0.0;
double temp = filtersequence;
while (temp > 0.0)
{
double groupMultiplier = 100.0;
double singleFilter = fmod(temp, groupMultiplier);
temp = floor(temp / groupMultiplier);
reverseString = reverseString * groupMultiplier + singleFilter;
}
NSLog(#"reversed string of filter %f", reverseString);
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
outputGroupReversed(1020304050.0);
}
return 0;
}
This code does not handle input with a fractional part correctly, though.

You're better off just converting it to a string and reversing it.
NSString *inputString = [#(input) stringValue]; // Eg 1230
NSMutableString *reversedString = [NSMutableString string];
NSInteger charIndex = [inputString length];
while (charIndex > 0) {
charIndex--;
NSRange subStrRange = NSMakeRange(charIndex, 1);
[reversedString appendString:[inputString substringWithRange:subStrRange]];
}
double result = [reversedString doubleValue]; // Eg 0321 -> 321
// Go back to NSString to get the missing length
NSString *resultString = [#(result) stringValue]; // Eg. 321
// Multiple by factors of 10 to add zeros
result *= exp(10, [inputString length] - [resultString length]); // 3210
NSLog(#"reversed value %f", result);
Reverse string method from this answer.

If you wish to store 2-digit decimal integers packed together as a single numeric value you would be better of using uint64_t - unsigned long 64 bit integers rather than double. That will store 9 pairs of two decimal digits precisely which appears to be one more than you need (you mention 16 digits in a comment).
As long as the numeric value of the packed pairs is not important, just that you can pack 8 2-digit decimal numbers (i.e. 0 -> 99) into a single numeric value, then you can do better. A 64-bit integer is 8 pairs of 2-hexadecimal digit numbers, or 8 8-bit bytes, so you can store 8 values 0 -> 99 one per byte. Now adding and extracting values becomes bit-shifts (>> & << operators) by 8 and bitwise-or (|) and bitwise-and (&). This at least makes it clear you are packing values in, which divide & remainder do not.
But there is another payoff, your "reverse" operation now becomes a single call to CFSwapInt64() which reverses the order of the bytes.
However having said the above, you really should look at your model and consider another data type for what you are doing - long gone are the days when programs had to pack multiple values into words to save space.
For example, why not just use a (C) array of 8-bit (uint8_t values[8]) integers? If you require you can place that in a struct and pass it around as a single value.

Related

Converting an audio file to char and sending to another device to listen to

I'm new in objective-C and I'm not getting to converting an audio file to char exactly I need. It is ignoring a sequence of zeros (0) and it's deforming the data structure.
My code is so:
-(NSString *) dataToHex:(NSData*) data {
const unsigned char *dbytes = (unsigned char*)[data bytes];
NSMutableString *hexStr =
[NSMutableString stringWithCapacity:[data length]/**2*/];
int i;
for (i = 0; i < [data length]; i++) {
[hexStr appendFormat:#"%x", dbytes[i]];
}
return [NSString stringWithString: hexStr];
}
Thank you very much.
If I understand your problem correctly the issue is with your format %x - this produces a hexadecimal text representation with sufficient digits to represent the value and without any leading zeroes.
For example the value 32 will produce the text 20, while the value 12 produces c - only one character long.
If you wish to convert to hex representation and then back again each of your byte values needs to produce the same number of characters - as otherwise you can't know where the boundaries are between each byte's representation.
To do this you can use the format %02x, which means always produce two characters padding with zeroes as required. For example with this format 12 will produce 0c.
HTH

Count number of arbitrary repeating decimal numbers in NSString

In my code, I'm dealing with an NSString that contains an NSNumber value. This NSNumber value could possibly be a repeating decimal number (e.x. 2.333333333e+06) that shortens to "2.333333" in a string format. It could also be a terminating number (e.x. 2.5), negative, or irrational number (2.398571892858...) (only dealing with decimals here)
I need to have a way to figure out if there are the repeating numbers in the string (or the NSNumber, if necessary). In my code, I would have no way to know what the repeating number would be, as it's a result of computations started by the user. I have tried this for loop (see below) that doesn't work the way I want it to, due to my inexperience with string indexing/ranges/lengths.
BOOL repeat = NO; //bool to check if repeating #
double repNum, tempNum; //run in for loop
NSString *repeating = [numVal stringValue]; //string that holds possible repeating #
for (int i = 3; i <= [repeating length]-3; i++) { //not sure about index/length here
if (i == 3) {
repNum = [repeating characterAtIndex:i];
}
tempNum = [repeating characterAtIndex:i];
if (tempNum == repNum) {
repeat = YES;
} else {
repeat = NO;
}
}
This code doesn't work as I'd like it to, mainly because I also have to account for negative dashes in the string and different amounts of numbers (13 1/3 vs. 1 1/3). I've used the modffunction to separate the integers from the decimals, but that hasn't worked well for me either.
Thank you in advance. Please let me know if I can clarify anything.
EDIT:
This code works with the finding of different solutions for polynomials (quadratic formula). Hope this helps put it into context. See here. (Example input)
NSNumber *firstPlusSolution, *secondMinusSolution;
NSString *pValueStr, *mValueStr;
firstPlusSolution = -(b) + sqrt(square(b) - (4)*(a)*(c)); //a, b, c: "user" provided
firstPlusSolution /= 2*(a);
secondMinusSolution = -(b) - sqrt(square(b) - 4*(a)*(c));
secondMinusSolution /= 2*(a);
pValueStr = [firstPlusSolution stringValue];
mValueStr = [secondMinusSolution stringValue];
if ([NSString doesString:pValueStr containCharacter:'.']) { //category method I implemented
double fractionPart, integerPart;
fractionPart = modf(firstPlusSolution, &integerPart);
NSString *repeating = [NSString stringWithFormat:#"%g", fractionPart];
int repNum, tempNum;
BOOL repeat = NO;
//do for loop and check for negatives, integers, etc.
}
if ([NSString doesString:mValueStr containCharacter'.']) {
//do above code
//do for loop and check again
}
Use C. Take the fractional part. Convert to a string with a known accuracy. If length of string indicates that last digits are missing, then it does not repeat. Use NSString-UTF8String to convert a string. Get rid of the last digit (may be rounding or actual floating point arithmetic error). Use function int strncmp ( const char * str1, const char * str2, size_t num ) to perform comparison within the string itself. If the result is 8 characters long and the last 2 characters match the first 2 characters, then shall the first 6 characters be considered repeating?
Assuming that fraction knowledge your desire:
• Possibility 1: Use fractions. Input fractions. Compute with fractions. Output fractions. Expand upon one of the many examples of a c++ fraction class if necessary and use it.
• Possibility 2: Choose an accuracy which is much less than double. Make a fraction from the result. Reduce the fraction allowing rounding based upon accuracy.
I suggest use not optimal but easy to write solution
Create NSMutableDictionary that will contain number as key and count of occurrence as value.
You can use componentsSeparatedByString: if numbers in string delimited by known symbol
In loop check valueForKey in dictionary and if need increase value
Last step is analyzing our dictionary and do anything you need with numbers

Objective-C: Flooring to 3 decimals correctly

I am trying to floor a float value to the third decimal. For example, the value 2.56976 shall be 2.569 not 2.570. I searched and found answers like these:
floor double by decimal place
Such answers are not accurate. For example the code:
double value = (double)((unsigned int)(value * (double)placed)) / (double)placed
can return the value - 1 and this is not correct. The multiplication of value and placed value * (double)placed) could introduce something like: 2100.999999996. When changed to unsigned int, it becomes 2100 which is wrong (the correct value should be 2101). Other answers suffer from the same issue. In Java, you can use BigDecimal which saves all that hassels.
(Note: of course, rounding the 2100.9999 is not an option as it ruins the whole idea of flooring to "3 decimals correctly")
The following code should work:
#include <stdio.h>
#include <math.h>
int main(void) {
double value = 1.23456;
double val3;
val3 = floor(1000.0 * value + 0.0001) * 0.001; // add 0.0001 to "fix" binary representation problem
printf("val3 is %.8f; the error is %f\n", val3, 1.234 - val3);
}
this prints out
val3 is 1.23400000; the error is 0.000000
If there are any residual errors, it comes about from the fact that floating point numbers cannot necessarily be represented exactly - the idea behind BigDecimal and things like that is to work around that in a very explicit way (for example by representing a number as its digits, rather than a binary representation - it's less efficient, but maintains accuracy)
I had to consider a solution involving NSString and it worked like a charm. Here is the full method:
- (float) getFlooredPrice:(float) passedPrice {
NSString *floatPassedPriceString = [NSString stringWithFormat:#"%f", passedPrice];
NSArray *floatArray = [floatPassedPriceString componentsSeparatedByString:#"."];
NSString *fixedPart = [floatArray objectAtIndex:0];
NSString *decimalPart = #"";
if ([floatArray count] > 1) {
NSString *decimalPartWhole = [floatArray objectAtIndex:1];
if (decimalPartWhole.length > 3) {
decimalPart = [decimalPartWhole substringToIndex:3];
} else {
decimalPart = decimalPartWhole;
}
}
NSString *wholeNumber = [NSString stringWithFormat:#"%#.%#", fixedPart, decimalPart];
return [wholeNumber floatValue];
}
For example, the value 2.56976 shall be 2.569 not 2.570
Solution is has simple as that :
double result = floor(2.56976 * 1000.0) / 1000.0;
I don't know why you search complication... this works perfectly, doesn't need to pass by some unsigned int or other + 0.0001 or whatever.
Important note :
NSLog(#"%.4f", myDouble);
Actually do a round on your variable. So it's improper to believe you can floor with a %.Xf

Convert really large decimal string to hex?

I've got a really large decimal number in an NSString, which is too large to fit into any variable including NSDecimal. I was doing the math manually, but if I can't fit the number into a variable then I can't be dividing it. So what would be a good way to convert the string?
Example Input: 423723487924398723478243789243879243978234
Output: 4DD361F5A772159224CE9EB0C215D2915FA
I was looking at the first answer here, but it's in C# and I don't know it's objective C equivalent.
Does anyone have any ideas that don't involve using an external library?
If this is all you need, it's not too hard to implement, especially if you're willing to use Objective-C++. By using Objective-C++, you can use a vector to manage memory, which simplifies the code.
Here's the interface we'll implement:
// NSString+BigDecimalToHex.h
#interface NSString (BigDecimalToHex)
- (NSString *)hexStringFromDecimalString;
#end
To implement it, we'll represent an arbitrary-precision non-negative integer as a vector of base-65536 digits:
// NSString+BigDecimalToHex.mm
#import "NSString+BigDecimalToHex.h"
#import <vector>
// index 0 is the least significant digit
typedef std::vector<uint16_t> BigInt;
The "hard" part is to multiply a BigInt by 10 and add a single decimal digit to it. We can very easily implement this as long multiplication with a preloaded carry:
static void insertDecimalDigit(BigInt &b, uint16_t decimalDigit) {
uint32_t carry = decimalDigit;
for (size_t i = 0; i < b.size(); ++i) {
uint32_t product = b[i] * (uint32_t)10 + carry;
b[i] = (uint16_t)product;
carry = product >> 16;
}
if (carry > 0) {
b.push_back(carry);
}
}
With that helper method, we're ready to implement the interface. First, we need to convert the decimal digit string to a BigInt by calling the helper method once for each decimal digit:
- (NSString *)hexStringFromDecimalString {
NSUInteger length = self.length;
unichar decimalCharacters[length];
[self getCharacters:decimalCharacters range:NSMakeRange(0, length)];
BigInt b;
for (NSUInteger i = 0; i < length; ++i) {
insertDecimalDigit(b, decimalCharacters[i] - '0');
}
If the input string is empty, or all zeros, then b is empty. We need to check for that:
if (b.size() == 0) {
return #"0";
}
Now we need to convert b to a hex digit string. The most significant digit of b is at the highest index. To avoid leading zeros, we'll handle that digit specially:
NSMutableString *hexString = [NSMutableString stringWithFormat:#"%X", b.back()];
Then we convert each remaining base-65536 digit to four hex digits, in order from most significant to least significant:
for (ssize_t i = b.size() - 2; i >= 0; --i) {
[hexString appendFormat:#"%04X", b[i]];
}
And then we're done:
return hexString;
}
You can find my full test program (to run as a Mac command-line program) in this gist.

Binary conversion algorithm in objective-c

How do I get the value of a certain bit from a byte or integer? The only similar answer that I've been able to find is for a specific character inside a string. I am trying to convert a binary number to a decimal number, and perhaps there is a much simpler way to do this, but I was thinking of this: multiplying 2^(position of integer from right) by either a 1 or 0, depending on the value of the integer at the position previously mentioned. Any tips?
NSString * binary = #"0011010";
long value = strtol([b UTF8String], NULL, 2);
There are multiways of obtaining the value of bit within a byte or integer. It all depends on your needs.
One way would be to use a mask with bitwise operators.
int result = sourceValue & 8; // 8 -> 0x00001000
// result non zero if the 4th bit from the right is ON.
You can also shift bits one by one and read, say, the right-most bit.
for (int i = 0; i < 8; i++)
NSLog(#"Bit %d is %#", i, (sourceValue % 2 == 0) ? #"OFF" : #"ON");
sourceValue = sourceValue >> 1; // shift bits to the right for next loop.
}
Or if you just want the text representation for an integer, you could let NSNumber do the work:
NSString* myString = [[NSNumber numberWithInt:sourceValue] stringValue];