Inconsistency converting decimal to double (Objective C) - objective-c

XCode 9.4.1. In debugger console I see results that seem strange to me:
(lldb) print (double)0.07
(double) $0 = 0.070000000000000007
(lldb) print [(NSDecimalNumber*)[NSDecimalNumber decimalNumberWithString:#"0.07"] doubleValue]
(double) $1 = 0.069999999999999993
The same results I see if executing in compiled code. I don't understand why result is different when converting literal 0.07 to double, and when converting decimal 0.07 to double. Why precision is lost differently?
What am I missing?

The values are calulated differently
(lldb) p 7.0 / 100.0
(double) $0 = 0.070000000000000007
(lldb) p 7.0 / 10.0 / 10.0
(double) $1 = 0.069999999999999993

NSDecimalNumber is designed to behave exactly like what you're seeing. It does "base 10 math" to avoid the very issue you are seeing -- traditional floating point representation of numbers can't accurately represent the base 10 numbers we're used to writing.
The comment instructing you to "go study numerical methods" is a bit brash but it's kind of heading in the right direction. A better use of your time would be to (also) take a look at the documentation for NSDecimalNumber and think about what it does and why it exists.
I had never heard of NSDecimalNumber before a couple minutes ago, so thanks for pointing me at some new knowledge. :-)

Related

Formatting in Raku

I have written a function that outputs a double, upto 25 decimal
places. I am trying to print it as a formatted output from Raku.
However, the output is incorrect and truncated.
See MWE:
my $var = 0.8144262510988963255087469;
say sprintf("The variable value is: %.25f", $var)
The above code gives The variable value is: 0.8144262510988963000000000 which is not what is expected.
Also, this seems weird:
my $var = 0.8144262510988963255087469;
say $var.Str.chars; # 29 wrong, expected 27
I tested the same in C:
#include <stdio.h>
int main() {
double var = 0.8144262510988963255087469;
printf("The variable value is: %.25lf \n", var);
return 0;
}
However, it works fine. Given the identical nature of sprintf and printf, I expected this C example to work in Raku too. Seems like %lf is not supported.
So is there a workaround to fix this?
I think this is actually a bug in how Rat literals are created. Or at least as WAT :-).
I actually sort of expect 0.8144262510988963255087469 to either give a compile time warning, or create a Num, as it exceeds the standard precision of a Rat:
raku -e 'say 0.8144262510988963255087469'
0.814426251098896400086204416
Note that these are not the same.
There is fortunately an easy workaround, by creating a FatRat
$ raku -e 'say 0.8144262510988963255087469.FatRat'
0.8144262510988963255087469
FWIW, I think this is worthy of creating an issue
From your question:
I have written a function that outputs a double, upto 25 decimal places.
From google:
Double precision numbers are accurate up to sixteen decimal places
From the raku docs :
When constructing a Rat (i.e. when it is not a result of some mathematical expression), however, a larger denominator can be used
so if you go
my $v = 0.8144262510988963255087469;
say $v.raku;
#<8144262510988963255087469/10000000000000000000000000>
it works.
However, do a mathematical expression such as
my $b = $a/10000000000000000000000000;
and you get the Rat => Num degradation applied unless you explicitly declare FatRats. I visualise this as the math operation placing the result in a Num register in the CPU.
The docs also mention that .say and .put may be less faithful than .raku, presumably because they use math operations (or coercion) internally.
Sorry to be the bearer of bad news, but 10**25 > 2 **64, but what you report as an issue is correct & (fairly) well documented behaviour given the constraints of double precision IEEE P754.

Can I make printf format floats like C++ streams

I am comparing the output of two programs, one C the other C++, using diff, so the output must be identical.
Is there any way to printf a double so that it is formatted as though it was printed using << mydouble.
I am currently using printf("%g",mydouble)
Here are some examples of the differences:
c: 3.24769e-05 c++: 3.2477e-05
c: 0.0026572 c++: 0.00265721
Interestingly the scientific notation has more digits in c, and the decimal notation has more in c++.
You can solve this by using the format specifiers in C.
For example, say you would like to print out only 3 places after the decimal, you could make your printf like so:
printf("%.3lf", dub);
With a value of double dub = .0137; the output would be 0.014
This would fix the issue with your 2nd case if you want more precision printed you could write:
printf("%.8lf", dub);
Your output for double dub = 0.00265721; would then be 0.00265721
The case for %g works the same way except the number on the left is included in the calculation. If you wanted the C++ version (the lesser precision I assume) then your code would look like this:
double dub = .0000324769;
printf("%.5g", dub);
Which yields 3.2477e-05

How to print formatted float in obj-c?

How to print a float in Objective-C as, for example, 3.45 instead of 3.45555555555?
Try formatting the float like this:
NSLog(#"%.2f", myFloat);
The % sign means this will be replaced by the corresponding argument following (myFloat). The .2 means 2 decimal places, and f means a float datatype.
Take a look here for more detail.
Objective-C's NSLog is very similar to C's printf, with the main exceptions being that you must use an Objective-C string literal (#"…") and you should use %# for Objective-C strings (NSStrings) rather than %s, which is for "Plain C strings".
Depends on how you're printing it. If you want to show it in a GUI (which is probably the common case for Cocoa and Cocoa Touch apps), use an NSNumberFormatter and set it to have two decimal places. If you're printing it through NSLog() or printf(), you'd use a format specifier along the lines of "%.2f".

Rounding doubles for use in NSString

I have a situation where I have lots of different double values, for example 1.00, 0.25 and 2.50. I would like to round these doubles so that they become 1, 0.25 and 2.5; in other words I want to remove any trailing 0's. Is there a way to do this?
At the moment I have been using %.2f, and I'm wondering if I can make use of this but adapt it in some way. Please can someone help me out?
As long as you're talking only about display, this is quite easy. The format specifier you want is %g:
The double argument shall be converted in the style f or e (or in the style F or E in the case of a G conversion specifier), with the precision specifying the number of significant digits [...] Trailing zeros shall be removed from the fractional portion of the result[...]
double twopointfive = 2.500;
double onepointzero = 1.0;
double pointtwofive = .25000000000;
NSLog(#"%g %f", twopointfive, twopointfive);
NSLog(#"%g %f", onepointzero, onepointzero);
NSLog(#"%g %f", pointtwofive, pointtwofive);
2011-12-06 21:27:59.180 TrailingZeroes[39506:903] 2.5 2.500000
2011-12-06 21:27:59.184 TrailingZeroes[39506:903] 1 1.000000
2011-12-06 21:27:59.185 TrailingZeroes[39506:903] 0.25 0.250000
The same format specifier can be used with an NSNumberFormatter, which will also give you some control over significant digits.
The trailing zeroes can't be removed from the way the number is stored in memory, of course.
I believe you want the %g format specifier to redact trailing zeros.
Not really rounding, but have you tried just %f it should only show the number of digits required rather then padding out the number.
My answer above is wrong, %g as others has stated is the right way to go.
The documentation for string formatters should help too. http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265
Here is a list of all the format specifiers that you can use...
%# Object
%d, %i signed int
%u unsigned int
%f float/double
%x, %X hexadecimal int
%o octal int
%zu size_t
%p pointer
%e float/double (in scientific notation)
%g float/double (as %f or %e, depending on value)
%s C string (bytes)
%S C string (unichar)
%.*s Pascal string (requires two arguments, pass pstr[0] as the first, pstr+1 as the second)
%c character
%C unichar
%lld long long
%llu unsigned long long
%Lf long double

printing floating point numbers in D

It's been quite a while since I last used D Programming Language, and now I'm using it for some project that involves scientific calculations.
I have a bunch of floating point data, but when I print them using writefln, I get results like: 4.62593E-172 which is a zero! How do I use string formatting % stuff to print such things as 0?
Right now I'm using a hack:
if( abs(a) < 0.0000001 )
writefln(0);
else
writefln(a);
it does the job, but I want to do it using the formatting operations, if possible.
UPDATE
someone suggested writefln("%.3f", a) but the problem with it is that it prints needless extra zeros, i.e. 0 becomes 0.000 and 1.2 becomes 1.200
Can I make it also remove the trailing zeros?
Short answer: This can't be done with printf format specifiers.
Since D uses the same formatting as C99's vsprintf(), you find your answer in this thread: Avoid trailing zeroes in printf()
Try something like
writefln("%.3f", a);
Federico's answer should work, for more information check the format specifiers section.
I see you are currently using Phobos, however what you are trying to do is supported in Tango.
Stdout.formatln("{:f2}", 1.2);
will print "1.20"