I have the following code:
double d1 = 12.123456789012345;
NSString *test1 = [NSString stringWithFormat:#"%f", d1]; // string is: 12.123457
NSString *test1 = [NSString stringWithFormat:#"%g", d1]; // string is: 12.1235
How do I get a string value that is exactly the same as d1?
It may help you to take a look at Apple's guide to String Format Specifiers.
%f 64-bit floating-point number
%g 64-bit floating-point number (double), printed in the style of %e if the exponent is less than –4 or greater than or equal to the precision, in the style of %f otherwise
Also read up on floating point (in)accuracy, and, of course What Every Computer Scientist Should Know About Floating-Point Arithmetic.
If you really want the string to match the double exactly, then use NSString to encode it and call doubleValue when you want the value. Also take a look at NSNumberFormatter.
How about
NSString *test1 = [NSString stringWithFormat:#"%.15f", d1];
Or simply go for the double as
NSString *test1 = [NSString stringWithFormat:#"%lf", d1];
Related
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.
I have 53.025709438664 in string when I do [string_variable doubleValue], I get 53.025709.
I use NSLog(#"%f") to print it.
How I can get full precision value ?
Please have a look at the format specifiers provided in Apple doc.
You cannot get all the digits after decimal point.
Edit:
If you know exact number of digits after decimal, then we could use something as follows
NSString *s = #" 53.025709438664";
double d = [s doubleValue];
NSLog(#"%.12f",d);
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
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.
I have the following code that is meant to convert milliseconds into hours, mins and seconds:
int hours = floor(rawtime / 3600000);
int mins = floor((rawtime % 3600000) / (1000 * 60));
int secs = floor(((rawtime % 3600000) % (1000 * 60)) / 1000);
NSLog(#"%d:%d:%d", hours, mins, secs);
NSString *hoursStr = [NSString stringWithFormat:#"%d", hours];
NSString *minsStr = [NSString stringWithFormat:#"%d", mins];
NSString *secsStr = [NSString stringWithFormat:#"%d", secs];
NSLog(#"%a:%a:%a", hoursStr, minsStr, secsStr);
Fairly straightforward. Rawtime is an int with value 1200. The output is like this:
0:0:1
0x1.3eaf003d9573p-962:0x1.7bd2003d3ebp-981:-0x1.26197p-698
Why is it that converting the ints to strings gives such wild numbers? I've tried using %i and %u and they made no difference. What is happening?
You have to use %# as the conversion specifier for an NSString. Change your last line to:
NSLog(#"%#:%#:%#", hoursStr, minsStr, secsStr);
%a means something totally different. From the printf() man page:
aA
The double argument is rounded and converted to hexadecimal notation in the style
[-]0xh.hhhp[+-]d
where the number of digits after the hexadecimal-point character is equal to the precision specification.
Instead of rolling your own string formatting code, you should be using an NSNumberFormatter for numbers or an NSDateFormatter for dates/times. These data formatters take care of localization of format to the user's locale and handle a variety of formats built-in.
For your use, you need to convert your millisecond time into an NSTimeInterval (typedef'd from a double):
NSTimeInterval time = rawtime/1e3;
Now you can use an NSDateFormatter to present the time:
NSDate *timeDate = [NSDate dateWithTimeIntervalSinceReferenceDate:time];
NSString *formattedTime = [NSDateFormatter localizedStringFromDate:timeDate
dateStyle:NSDateFormatterNoStyle
timeStyle:NSDateFormatterMediumStyle];
NSString *rawTime = [[formattedTime componentsSeparatedByString:#" "] objectAtIndex:0];
on OS X where the last line removes the "AM/PM". This will work for any time less than 12 hrs and will give a formatted string in the localized format for HH:MM:SS. On the iPhone, localizedStringFromDate:dateStyle:timeStyle: isn't available (yet). You can achieve the same effect with setTimeStyle:, setDateStyle: and stringFromDate: on a date formatter instance.