Convert float to float and truncate after two decimal places Objective-C - iphone

I have a float var1 = cashInHandAmount = 4.73000002
I simply want as:
var2 = 4.73.
I have tried like this:
NSString *floatString = [NSString stringWithFormat:#"%.02f",cashInHandAmount];//it prints 4.73
[self.editcash setMaxValue:[floatString floatValue]];//but it again sets 4.73000002 why?
can you guys please help me regarding this?

%f simply rounds for the output. Transforming a float value into a string and back does not work, if the exact value (i. e. 4.73) has no representation in the float format. So transforming it back will "round" the stored value 4.73 into the float format, which is obviously 4.730…02.
You should rarely use (binary, IEEE) floats for financial calculating. Financial values (amount of money) is in most cases an integral value of cents, but no float value of dollars (or whatever). Additionally you can think about using NSDecimal and NSDecimalNumber to ensure, that every value with two digits of precision is storable in the format.
Edit:
float f = 4.73000002;
float rounded = roundf(f * 100.0f) / 100.0f;
NSLog(#"%10.10f", rounded);
outputs:
2014-07-01 10:25:48.653 xctest[596:303] 4.7300000191
It is difficult to check, but probably float can not represent 4.73 exactly. The nearest representable value is 4.7300000191. This is what I said: A rounded decimal representation is not always a possible "binary float" representation. You will face that problem with many values.

Try this :
float var1 = 4.73000002;
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
formatter.maximumFractionDigits = 2; //Set number of fractional digits
NSNumber *num = [NSNumber numberWithFloat:var1];
NSString *roundedNum = [formatter stringFromNumber:num];
DLOG(#"Answer : %#", roundedNum);

If you want truncate all other decimals you can declare a simple method like this:
- (float)sanitizeFloat:(float)value
{
float newValue = [[NSString stringWithFormat:#"%.2f",value] floatValue];
return newValue;
}
and then
float aFloat = 45.070809;
NSLog(#"%f",[self sanitizeFloat:aFloat]);
In your case:
[self.editcash setMaxValue:[self sanitizeFloat:cashInHandAmount]];
The output will be 45.070000

If you're working with monetary amounts that have fixed decimal places, you should always use NSDecimal or NSDecimalNumber - you shouldn't use floats at all, as they are inexact.
You could use:
-[NSDecimalNumber decimalNumberWithString:]
to create your number, and there are many methods for working with NSDecimalNumbers - see Apple's docs or NSDecimalNumber.h for details.

Related

How to convert NSDecimalNumber to CLLocationDegrees without losing precision?

I need to convert NSDecimalNumber with lat/lon values which I need to convert to CLLocationDegrees. I used -[NSDecimalNumber doubleValue] method. But the value loses its precision. I want the values to be same. The following is what I am talking about(I hope everyone would be aware about this issue already).
NSString *coordStr = #"-33.890934125621094";
NSDecimalNumber *lat = [NSDecimalNumber decimalNumberWithString:coordStr];
NSLog(#"%#", lat); // -33.890934125621094
NSLog(#"%lf", [lat doubleValue]); // -33.890934
Is there any way that I should do instead of doing the above?
Try out to convert the String with the doubleValue method
NSString *coordStr = #"-33.890934125621094";
NSLog(#"%.17g",coordStr.doubleValue); //-33.890934125621094
Check out this post: How to print a double with full precision on iOS?
edit:
the docu says: typedef double CLLocationDegrees; so you can double test = coordStr.doubleValue; the problem is only, that NSLog doesn't print the complete value. but instead the double var saves the complete value.
CLLocationDegree is a double. So the maximum precision can only equal that of a double datatype.

Removing characters after the decimal point for a double

How can I remove the all the characters after the decimal point.
Instead of 7.3456, I would just like 7.
This is what I do to get the number so far with decimal places.
[NSString stringWithFormat:#" %f : %f",(audioPlayer.currentTime),(audioPlayer.duration) ];
Many Thanks,
-Code
You can specify what you want using format string :
[NSString stringWithFormat:#" %.0f : %.0f", (audioPlayer.currentTime),
(audioPlayer.duration)];
If you want this for display, use an NSNumberFormatter:
double sevenpointthreefourfivesix = 7.3456;
NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:0];
NSLog(#"%#", [formatter stringFromNumber:[NSNumber numberWithDouble:sevenpointthreefourfivesix]]);
2011-12-20 20:19:48.813 NoDecimal[55110:903] 7
If you want a value without the fractional part, use round(). If you want the closest integer value not greater than the original value, use floor().
floorf() is the function you're looking for.
you are after
[NSString stringWithFormat:#" %.00f : %.00f",(audioPlayer.currentTime),(audioPlayer.duration) ];
When formatting float you can tell the precision by the number before the f
Cast to int:
[NSString stringWithFormat:#" %i : %i",(int)(audioPlayer.currentTime),(int)(audioPlayer.duration) ];
Casting like this always rounds down (eg: just removes everything after the decimal place). This is what you asked for.
In the case of rounding to the NEAREST whole number you want to add 0.5 to the number
[NSString stringWithFormat:#" %i : %i",(int)(audioPlayer.currentTime+0.5f),(int)(audioPlayer.duration+0.5f) ];
This will round to the nearest whole number. eg: 1.2 becomes 1.7 and casting to int makes 1. 3.6 becomes 4.1 and casting makes 4. :)
Why not just cast the audioPlayer.currentTime to an integer before you use stringWithFormat?
[NSString stringWithFormat:#"%d", (int)(audioPlayer.currentTime)];
All you need to do is type-cast the double to an int, like so: int currentTime_int = (int)audioPlayer.currentTime;.
You can use this same approach for the other variable.
Many of the shorter answers here will work correctly. But if you want your code to be really clear and readable, you might want to explicitly specify your desired conversion from float to int, such as using:
int tmpInt = floorf(myFloat); // or roundf(), etc.
and then separately specifying how you want the integer formated, e.g.
... stringWithFormat:#"%d", tmpInt ... // or #"%+03d", etc.
instead of assuming that an inline cast shows what you want.
You may also use
double newDvalue =floor(dValue);
it will remove all the decimals point
using %.0f for string format will be good also

NSDecimalNumber to unsignedLongLong - wrong value

Here is code:
NSNumber* number = [NSDecimalNumber decimalNumberWithString :#"11111111111111111"];
NSLog(#"%# = %lld", number, [number unsignedLongLongValue]);
And I get output:
11111111111111111 = 11111111111111112
Is it known bug or I do something wrong?
UPDATE:
bug reported: https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/3/wo/Stnn5Aaocknzx52c64zbN0/5.83.28.0.9
I believe the issue is that you are using NSNumber's -longLongValue method on an NSDecimalNumber. NSDecimalNumber stores a high-precision representation of the number internally as a decimal, but NSNumber just keeps it as an IEEE 754 double precision floating-point value. If I recall correctly, if you use the standard NSNumber superclass methods on an NSDecimalNumber, the internal number is first converted to a double, which can introduce binary floating-point artifacts like this.
As neoneye suggests, a way around this might be to use an NSString as an intermediary. For example:
NSDecimalNumber* number = [NSDecimalNumber decimalNumberWithString :#"11111111111111111"];
double number2 = [#"11111111111111111" doubleValue];
NSLog(#"%# = %lld = %f", number, [[number descriptionWithLocale:nil] longLongValue], number2);
Will produce the result 11111111111111111 = 11111111111111111 = 11111111111111112.000000, showing both the correct result from the decimal number extraction and the error that happens when this number is temporarily stored in a double.

How to display currency without rounding as string in Xcode?

I have trouble when I have currency value
999999999999999999.99
From that value, I want to display it as String. The problem is that value always rounded to
1000000000000000000.00
I'm not expect that value rounded. I want the original value displayed. Do you have any idea how to solve this problem? I tried this code from some answer/turorial in stackoverflow.com :
NSMutableString *aString = [NSMutableString stringWithCapacity:30];
NSNumberFormatter *aCurrency = [[NSNumberFormatter alloc]init];
[aCurrency setFormatterBehavior:NSNumberFormatterBehavior10_4];
[aCurrency setNumberStyle:NSNumberFormatterCurrencyStyle];
[aCurrency setMinimumFractionDigits:2];
[aCurrency setMaximumFractionDigits:2];
[aString appendString:[aCurrency stringFromNumber:productPrice]];
//productPrice is NSDecimalNumber which is have value 999999999999999999.99
cell.textLabel.text = aString;
NSLog(#"the price = %#",cell.textLabel.text);
//it prints $1,000,000,000,000,000,000.00
[aCurrency release];
Unless you have very good reasons not to, it is generally best to keep currency values in a fixed-point format, rather than floating point. Ada supports this directly, but for C-ish languages what you do is keep the value in units of pennies, rather than dollars, and only do the conversion whenever you go to display it.
So in this case the value of productPrice would be 99999999999999999999 (cents). To display it, you'd do something like this (If this were C. I don't know the language):
int const modulus = productPrice % 100;
printf ("The price = %d.%d\n", (int) ((productPrice - modulus) / 100), modulus);
I'd also use an integer rather than a floating point variable to keep the value in almost all cases. It won't work in this case (even if you use a 64-bit integer) because your value is mind-bogglingly large. We're talking 1 million times larger than the US National Debt! If a dollar value that large ever makes sense for anything in my lifetime, we are all in big trouble.
Have you tried these:
* – setRoundingBehavior:
* – roundingBehavior
* – setRoundingIncrement:
* – roundingIncrement
* – setRoundingMode:
* – roundingMode

Proper Usage and Formatting of a Float in Objective-C (or C)

I have an iPhone app. I am storing a float value, (distance), in my sqlite3 db. (The field in the db is formatted to float) I am able to store float values correctly in the db no problem. However, I can't seem to figure out how to pull the value back out of the db the format and present it correctly. Here is my code for pulling the value out of my db and using it:
NSString *itemDistance = [NSString stringWithFormat:#"%f",[item distance]];
float questionDistance = [itemDistance floatValue];
[item distance] is a float value. I can't get this to work. I get a REALLY long value instead. What am I doing wrong? Any help would be greatly appreciated.
Thank you in advance for your help,
L.
Assuming your -distance method is returning the right value, then this sounds like basic misunderstanding of how floats work in C. Common mistake. Every developer falls into this trap at least once.
Floating point numbers can actually only represent a fairly limited number of values. Specifically, unless you happen to choose a value that is exactly representable as a float, you'll get the nearest value, which will often have many decimal places of data.
The reason for this is because a float is only 32 bits; 4 bytes. Now, how many numbers with decimal points are there between 0..1000000 or 0..1000 or, even, 0..1. Infinite. Floats implement a very finite subset of possible numeric values and do so in a way where the resulting possible values may have many decimal places.
Consider:
printf("%5.18f\n", (float) 2.05);
printf("%5.18f\n", (float) 2.45);
printf("%5.18f\n", (float) 4200.75);
printf("%5.18f\n", (float) 37.89);
printf("%5.18f\n", (float) 1.2);
printf("%5.18f\n", (float) -1.2);
This prints:
2.049999952316284180
2.450000047683715820
4200.750000000000000000
37.889999389648437500
1.200000047683715820
-1.200000047683715820
Those values are as close to the values in the bit of code that a float could represent.
If you need more precision, use a double. More precision than that? Use NSDecimalNumber.
And, if you can, use CoreData. It makes managing this kind of thing a bit more straightforward.
why go round in circles?
NSString *itemDistance = [NSString stringWithFormat:#"%.2f",[item distance]];
float questionDistance = [itemDistance floatValue];
Where the .2 is saying I want 2 decimal places.
Whats the type of of distance? If it is an instance of NSNumber then I dont think the code you wrote will work, try
NSString *itemDistance = [[item distance] stringValue];
float questionDistance = [itemDistance floatValue];
or even
float q=[[item distance] floatValue];