Reducing the digits of a Double in C++ - c++

I need a function that reduces the precision (number of digits) of my doubles.
I need it for calculation, not for output on the screen.
What I have so far, is:
double setDigits(double _number, int _digits)
{
double tenth = pow((double)10,_digits);
_number *= tenth;
_number = floor(_number);
_number /= tenth;
return _number;
}
calling setDigits(sqrt(2),3) gives 1.4139999999999999, and not 1.414 as I want.
What can I do?

What can I do?
Unfortunately, nothing for the root problem: in your platform, 1.414 has no exact double representation. You can't run a calculation with "1.414" because you can't place "1.414" anywhere in your double.
See for example http://www3.ntu.edu.sg/home/ehchua/programming/java/DataRepresentation.html .
What you can do is to keep your number with the maximum precision, and display it with reduced precision. You need to calculate machine precision and keep track of error during computation.
So you'll use 1.413999999999997 and at the end get an answer of, say, 41.99999137; which you'll display with
printf("The answer is %.3f\n", theAnswer);
Or you can change platform (compiler, or math library, or floating point representation, e.g. use long double where supported), but remember that you can then get 1.414 right at the price of getting, say, 1.873 wrong (have it as 1.87299999999 or 1.87300000001), and the calculation will have more or less the same errors.
You can work in integer arithmetic, multiplying the initial numbers by 1,000,000 (and getting 1414000) or another suitable scale, and then dividing at the end. Integers have a maximum bound, though.
There are also Arbitrary Precision Libraries that use a different internal representation and allow you to specify precision the way you want, for example GMP ( http://gmplib.org/ ). Of course, working with that is more difficult than specifying
op1 = 6.0;
op2 = 7.0;
theAnswer = op1 * op2;
and processing is slower as well, but results are good - or as good as you tell them to be.

The following lines are invalid.
double tenth = pow((double)10,_decimals); //_decimals is not declared
_number = floor(_digits); //should be floor(_number)
The corrected function is
double setDigits(double _number, int _digits)
{
double tenth = pow((double)10,_digits);
_number *= tenth;
_number = floor(_number);
_number /= tenth;
return _number;
}
Here is a demo.

i don't know you may not check this answer but others do
i am new in c++ but i found a way to do this
double Point::norm()
{
return (double)floor((sqrt(pow(px,2)+pow(py,2)+pow(pz,2))*1000))*0.001;
}
i use this but you can write your own math class to do this for you

double setDigits(double _number, int _digits)
{
double tenth = pow((double)10,_digits);
int result = (_number * tenth) + 0.5;
double aux = result / tenth;
return aux;
}
Try the following with tenth = 1000;
result = 1413,9999999999999 * 1000 +0,5
result = 1414,4......
result = 1414

Try this:
double setDigits(double _number, int _digits)
{
double tenth = pow((double)10,_digits);
return floor(_number * tenth + 0.5)/tenth;
}
std::cout<<setDigits(sqrt(2),3);
Output: 1.414

You can create an intermediate class that manages data internally as int, but inputs and outputs as double:
class TruncatedDouble
{
private:
int value_;
public:
TruncatedDouble(double d) : value_((int)(double * 1000)) {}
void SetValue(double d) {value_ = (int)(double * 1000);}
double GetValue() {return (double)value_ / 1000;}
};
You have to overload all the usual operators too, but that's easy. Example:
TruncatedDouble& operator+=(const TruncatedDouble& rh) {value_ += rh.value_;}
And so on. This class will actually be quite fast, since you are operating with int instead of double, and you will never lose precision.

Related

Rounding a float number to a certain precision

I want to round a float to maximum 4 decimals places. It mean 0.333333333 will be 0.3333, but 0.33 is still 0.33
Use the std::round() function
The C++ standard library offers functions for performing rounding. For floats, it is:
float round ( float arg );
this will round arg to the nearest integral value. Now, you want a different decimal resolution. So don't round your value, round your value times 10000, so your singles digit is now the former 0.0001 digit. Or more generally:
float my_round(
float x,
int num_decimal_precision_digits)
{
float power_of_10 = std::pow(10, num_decimal_precision_digits);
return std::round(x * power_of_10) / power_of_10;
}
Note that there may be accuracy issues, as floating-point computations and representations are only accurate to within a certain number of digits, and in my_round we have at least four sources of such inaccuracy: The power-of-10 calculation, the multiplication, the devision and the actual rounding.
Cast it into a fixed-point type
If you want to have your results rounded, with a fixed number of decimal digits, you're hinting that you don't really need the "floating" aspect of floating point numbers. Well, in this case, cast your value to a type which represents such numbers. Essentially, that would be a (run-time-variable) integer numerator and a compile-time-fixed denominator (which in your case would be 10,000).
There's an old question here on the site about doing fixed-point math:
What's the best way to do fixed-point math?
but I would suggest you consider the CNL library as something recent/popular. Also, several proposals have been made to add fixed-point types to the standard library. I don't know which one is the farthest advance, but have a look at this one: Fixed-Point Real Numbers by John McFarlane.
Back to your specific case: Fixed-point types can typically be constructed from floating-point ones. Just do that.
Here is a solution, for example:
float ret = float(round(0.333333333 * 10000)) / 10000)
You can write it as a function. Maybe there would be a better way?
Assuming you need print rounded number, this is one of a proper solutions:
cout << setprecision(4) << x << '\n';
std::setprecision documentation.
Live demo
Until more details are not provided it is impossible to provide a better answer.
Please note if you are planing to round number x then print it, it will end with big headache, since some corner cases can produce much longer results then expected.
Use _vsnprintf
I think the best solution for this is to just format the string. Because what if we don't need to output this number to the console, but save it in a std::string variable or char[] or something like that. This solution is flexible because it is the same if you output a number to the console and used the std::setprecision() function, but also returning this number to char[].
So for this I used _vsnprintf and va_list. All it does is format the string as needed, in this case float value.
int FormatString(char* buf, size_t buf_size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
int w = _vsnprintf(buf, buf_size, fmt, args);
va_end(args);
if (buf == NULL)
return w;
if (w == -1 || w >= (int)buf_size)
w = (int)buf_size - 1;
buf[w] = 0;
return w;
}
int FormatStringFloat(char* buf, int buf_size, const void* p_data, const char* format) {
return FormatString(buf, buf_size, format, *(const float*)p_data);
}
Example
#include "iostream"
#include "string"
#define ARRAY_SIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR))))
int main() {
float value = 3.343535f;
char buf[64];
FormatStringFloat(buf, ARRAY_SIZE(buf), (void*)&value, "%.2f");
std::cout << std::string(buf) << std::endl;
return 0;
}
So by using "%.2f" we get from the 3.343535 => 3.34.

How to round off the totalcost (double) to nearest inetegrs

I have tried to search similar questions all over the net but non was useful for me.
The nearest I got to was "If the number before the .5 is odd round up, if even round down 13.5 turns into 14 but 12.5 turns into 12".
Coming to the question:
I simply need to calculate the total amount after a meal with the formula;
total amount = mealamount+ mealamount*tip% + mealamount *tax%
I came up with this piece of code (rough only)
#include<iostream>
#include<math.h>
#include <iomanip>
using namespace std;
int main () {
double mealCost;
double total=0;
double tipp,taxx=0;
cin>>mealCost;
int tip;
cin>>tip;
tipp=(tip*mealCost)/100;
int tax;
cin>>tax;
taxx=(tax*mealCost)/100;
total=mealCost+tipp+taxx;
cout << fixed << showpoint;
cout << setprecision(2);
cout<<total<<endl;
return 0;
}
but with the set of inputs of 10.75(mealamonut), 17(tip%),5 (tax %).
the value am getting is 12.50
if I use
int totalSum = std::round(total);
its getting converted to 12
but my requirement is 13 .
How to acheive that ?
I cannot find any duplicate question to this if exists
please mention.
There are multiple ways to convert doubles to integers. You have multiple kinds of round. Check them here, which are std::round, std::lround, std::llround.
On the other hand, if what you want to do is not rounding, but elimination of fractions into one direction, then you have std::ceil that goes always higher, and std::floor, that always goes lower.
Remember to include <cmath>, not <math.h>. The latter is for C, not C++
You achieve your goal by using std::ceil() and std::floor() which is defined under cmath header file.
You are trying to always round up so you would need to use the ceil() function. Ceil is short for ceiling and there is also a floor function. Ceiling is up, floor is down, here is a c snippet to try out.
#include <stdio.h> /* printf */
#include <math.h> /* ceil */
int main ()
{
printf ( "ceil of 2.3 is %.1f\n", ceil(2.3) );
printf ( "ceil of 3.8 is %.1f\n", ceil(3.8) );
printf ( "ceil of -2.3 is %.1f\n", ceil(-2.3) );
printf ( "ceil of -3.8 is %.1f\n", ceil(-3.8) );
return 0;
}
for rounding to nearest integer math.h has nearbyint
printf ( "nearbyint (2.3) = %.1f\n", nearbyint(2.3) );
printf ( "nearbyint (3.8) = %.1f\n", nearbyint(3.8) );
Output:
nearbyint (2.3) = 2.0
nearbyint (3.8) = 4.0
Or if you want to break the default rounding behavior when .5
int totalSum= (total - floor(total) ) >= 0.5 ? ceil(total) : floor(total);
1) 10.75 + 17*10.75/100 + 5*10.75/100 = 13.115 ... how comes I can't get 12.50?
2) How do you know it's 12.50, how do you check value of result? (it may be only 12.4999..., so when it is formatted to two decimal places, it will become 12.50) Make sure you do check the actual real value (ideally in debugger or dump memory content in bytes and reconstruct the value by hand), not some string formatted intermediate.
3) this is not some production code, right? Amounts are not calculated with doubles in real financial software, as doubles are not accurate enough and you would run into all kind of hard problems with rounding to VAT, etc. If this is some real thing, you are not up to the task, ask for help some professional.
Answer:
std::round should normally do what you need. If it's ending as 12, then it's because the value is less than 12.5.
If rounded to two decimal places it shows as 12.50, you are hitting one of those "all kind of hard problems" of real financial software.
Then you should create your own round using string representation, like this example (not handling negative numbers and reinventing wheel probably):
#include <iostream>
#include <string>
/**
* Rounds floating point value in std::string type.
* Works only for positive values, and without "+" sign!
* ie. regexp ~\d*\.?\d*~ formatting.
* For malformed input the output is undefined (but should not crash).
**/
std::string financialRound(const std::string & amount) {
const size_t dotPos = amount.find_first_of('.');
if (std::string::npos == dotPos) return amount; // no decimals found
// copy whole part into temporary result
std::string result = (0 < dotPos) ? amount.substr(0, dotPos) : "0";
const size_t firstDecimalPos = dotPos + 1;
// see if there is 5 to 9 digit after dot
if (amount.size() <= firstDecimalPos) return result; // no char
const char firstDecimal = amount.at(firstDecimalPos);
if (firstDecimal < '5' || '9' < firstDecimal) return result; //not 5-9
// add 1 to the result
int patchPos = (int)result.size();
while (0 <= --patchPos) {
++result.at(patchPos);
if ('9'+1 == result.at(patchPos)) result.at(patchPos) = '0';
else break;
}
// check if additional 1 is required (add overflow)
if (-1 == patchPos) result.insert(result.begin(), '1');
return result;
}
void tryValue(const std::string & amount) {
printf("\"%s\" is rounded to \"%s\"\n", amount.c_str(), financialRound(amount).c_str());
}
int main()
{
printf("Trying normal values...\n");
tryValue("12.50");
tryValue("12.49");
tryValue(".49");
tryValue(".50");
tryValue("9.49");
tryValue("9.50");
printf("Missing decimals...\n");
tryValue("12");
tryValue("12.");
printf("Malformed...\n");
tryValue("");
tryValue("a.4");
tryValue("a.5");
tryValue("12..");
}
live demo on cpp.sh

FP number's exponent field is not what I expected, why?

I've been stumped on this one for days. I've written this program from a book called Write Great Code Volume 1 Understanding the Machine Chapter four.
The project is to do Floating Point operations in C++. I plan to implement the other operations in C++ on my own; the book uses HLA (High Level Assembly) in the project for other operations like multiplication and division.
I wanted to display the exponent and other field values after they've been extracted from the FP number; for debugging. Yet I have a problem: when I look at these values in memory they are not what I think they should be. Key words: what I think. I believe I understand the IEEE FP format; its fairly simple and I understand all I've read so far in the book.
The big problem is why the Rexponent variable seems to be almost unpredictable; in this example with the given values its 5. Why is that? By my guess it should be two. Two because the decimal point is two digits right of the implied one.
I've commented the actual values that are produced in the program in to the code so you don't have to run the program to get a sense of whats happening (at least in the important parts).
It is unfinished at this point. The entire project has not been created on my computer yet.
Here is the code (quoted from the file which I copied from the book and then modified):
#include<iostream>
typedef long unsigned real; //typedef our long unsigned ints in to the label "real" so we don't confuse it with other datatypes.
using namespace std; //Just so I don't have to type out std::cout any more!
#define asreal(x) (*((float *) &x)) //Cast the address of X as a float pointer as a pointer. So we don't let the compiler truncate our FP values when being converted.
inline int extractExponent(real from) {
return ((from >> 23) & 0xFF) - 127; //Shift right 23 bits; & with eight ones (0xFF == 1111_1111 ) and make bias with the value by subtracting all ones from it.
}
void fpadd ( real left, real right, real *dest) {
//Left operand field containers
long unsigned int Lexponent = 0;
long unsigned Lmantissa = 0;
int Lsign = 0;
//RIGHT operand field containers
long unsigned int Rexponent = 0;
long unsigned Rmantissa = 0;
int Rsign = 0;
//Resulting operand field containers
long int Dexponent = 0;
long unsigned Dmantissa = 0;
int Dsign = 0;
std::cout << "Size of datatype: long unsigned int is: " << sizeof(long unsigned int); //For debugging
//Properly initialize the above variable's:
//Left
Lexponent = extractExponent(left); //Zero. This value is NOT a flat zero when displayed because we subtract 127 from the exponent after extracting it! //Value is: 0xffffff81
Lmantissa = extractMantissa (left); //Zero. We don't do anything to this number except add a whole number one to it. //Value is: 0x00000000
Lsign = extractSign(left); //Simple.
//Right
**Rexponent = extractExponent(right); //Value is: 0x00000005 <-- why???**
Rmantissa = extractMantissa (right);
Rsign = extractSign(right);
}
int main (int argc, char *argv[]) {
real a, b, c;
asreal(a) = -0.0;
asreal(b) = 45.67;
fpadd(a,b, &c);
printf("Sum of A and B is: %f", c);
std::cin >> a;
return 0;
}
Help would be much appreciated; I'm several days in to this project and very frustrated!
in this example with the given values its 5. Why is that?
The floating point number 45.67 is internally represented as
2^5 * 1.0110110101011100001010001111010111000010100011110110
which actually represents the number
45.6700000000000017053025658242404460906982421875
This is as close as you can get to 45.67 inside float.
If all you are interested in is the exponent of a number, simply compute its base 2 logarithm and round down. Since 45.67 is between 32 (2^5) and 64 (2^6), the exponent is 5.
Computers use binary representation for all numbers. Hence, the exponent is for base two, not base ten. int(log2(45.67)) = 5.

Random but predictable number generator? [C++]

Well I don't really know how to search for the thing I'm looking for.
Google gives tons of results, but none which match my criteria.
So I'm asking it here:
Is there any known piece of code that can create a number, that is predictable, looks random, and is based on a 'seed' (in my case it's the unix timestamp) and between a specified range?
I want to be able to create weather forecast in a script for a game I'm coding (but I need the C++ code which I can port, I don't think many people here are familiar with 'PAWN' [a.k.a. SMALL] scripting language? :) ).
The weather id's vary from 0 to ~100, including some deprecated ID's (so my solution would be to make a array holding valid weather ID's so we don't need to worry about those BAD_ID's, let's not make the function too complicated).
I could possibly make such formula but the problem in the past I had was that the weather was changing too fast (like every second, though I lost the code somewhere :/ ) and for now I'm really out of ideas on how I'm going to make such a formula.
Any suggestions are really appreciated too!
Look at the C implementation of the random number generator used by VB6. It's perfect for games because it generates fairly believable random seqeuences but uses a seed and the same seed always generates the same sequence. So in game data files you can save a set of seed values that will give you known (but random-looking) sequences that you can easily reproduce.
Here's an implementation that returns values in a range:
typedef int Int32;
typedef unsigned int UInt32;
class CRnd
{
private:
static const UInt32 INITIAL_VALUE = 0x50000;
static const UInt32 INCREMENT = 0xC39EC3;
static const UInt32 MULTIPLIER = 0x43FD43FD;
private:
UInt32 m_nRnd;
public:
CRnd () { m_nRnd = INITIAL_VALUE; };
CRnd ( IN UInt32 nSeed ) { m_nRnd = nSeed; };
virtual ~CRnd () {};
Int32 Get ( IN Int32 nFrom, IN Int32 nTo )
{
if ( nTo < nFrom ) // nFrom should be less than nTo
{
Int32 nTmp = nTo;
nTo = nFrom;
nFrom = nTmp;
}
else if ( nTo == nFrom )
{
return ( nTo );
}
m_nRnd = ( m_nRnd * MULTIPLIER + INCREMENT ) & 0xFFFFFF;
float fTmp = (float) m_nRnd / (float) 16777216.0;
return ( (Int32) ( ( fTmp * ( nTo - nFrom + 1 ) ) + nFrom ) );
};
void SetSeed ( IN UInt32 nSeed ) { m_nRnd = nSeed; };
UInt32 GetSeed () { return ( m_nRnd ); };
};
Look into srand and rand for starters.
C++11 includes many more advanced algorithms as well, but for basic needs the above two are sufficient.
To keep the numbers within a range of 0 to n, use the % operator.
Obviously a number cannot be both "predictable" and "random" - those are directly contradictory terms.
I'm assuming what you mean is a number that is both deterministic and semirandom.
Luckily for you, this is what pseudorandom number generators (PRNGs) produce: when they are run with a consistent seed, they give you the same output.
So I would recommend setting your seed with srandom, then using random() % MAX_VALUE to get a number between 0 and MAX_VALUE. If you get a "bad value", just go again. Repeat sans reseeding for as many numbers as you like.
If you need a slow changing value you can use a noise function, such as Perlin Noise.
What you really want is a hash function. To limit the range you can use one of the usual tricks (the dirtiest being the remainder operator).
Specifically, you want to hash integers into integers. You can pick up such a function here. I recommend the one titled "Robert Jenkins' 32 bit integer hash function" -- always worked well for me.
You'll end up with something like:
int time_index = 3;
int weather_state = integer_hash_function(time_index) % (MAX_VALUE - MIN_VALUE + 1) + MIN_VALUE
If you want more interesting weather behavior, you can linearly interpolate between time values. You can use Perlin noise with linear combinations of such interpolated noise at differing frequencies and intensities to make some pretty nice behavior. (I've done this with multiplayer RPGs and it works well.)
The problem with srand and rand is that only their call signatures (and not the values they generate) are dictated by the C standard. If you need portable and deterministic pseudo-random numbers, you should implement it yourself. Here is a class, written in C++, which is based on one found in Numerical Recipes, and is completely portable. You may instantiate the random number stream with a seed if you'd like to. I hard-code this seed instead of using the time in case I want the same pseudo-random sequence again and again. You can also use the RandomInteger(a,b) method to get integers on the half-open interval [a,b).
class RandomNumberStream
{
private:
unsigned long long u,v,w;
public:
RandomNumberStream(int n=1);
double RandomDouble();
double RandomDouble(double a, double b);
unsigned long long RandomInteger();
unsigned long long RandomInteger(int a, int b);
private:
unsigned long long int64();
} ;
RandomNumberStream::RandomNumberStream(int n)
{
v = 4101842887655102017LL;
w = 1;
u = n^v; int64();
v = u; int64();
w = v; int64();
}
double RandomNumberStream::RandomDouble()
{
return int64() * 5.42101086242752217E-20f;
}
double RandomNumberStream::RandomDouble(double a, double b)
{
return int64() * 5.42101086242752217E-20f * (b-a) + a;
}
unsigned long long RandomNumberStream::RandomInteger()
{
return int64();
}
unsigned long long RandomNumberStream::RandomInteger(int a, int b)
{
return a + int64() % (b-a);
}
unsigned long long RandomNumberStream::int64()
{
u = u * 2862933555777941757LL + 7046029254386353087LL;
v ^= v>>17; v ^= v<<31; v ^= v>>8;
w = 4294957665U*(w & 0xffffffff) + (w>>32);
unsigned long long x = u^(u<<21); x ^= x>>35; x ^= x<<4;
return (x+v)^w;
}
I think you can use rand for generating random numbers. However, you can give the same value to srand like say 99 so that your numbers will be random but predictable every time.
int iSecret = 0;
/* initialize random seed: */
srand ( 99 );
/* generate secret number: */
iSecret = rand();

scanf not taking in long double

i have problem with scanf not reading long double in the code below:
(please excuse my poor English)
#include <iostream>
#include <cstdlib>
#include <math.h>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
long double a,b,c,ha,hb,hc,ma,cosa,r,l,res,area;
for (int i=0;i<n;i++)
{
scanf("%Lf %Lf %Lf %Lf",&a,&ha,&hb,&hc);//this is where the problem lies,
//i need to read 4 long double a,ha,hb,hc
printf("%Lf %Lf %Lf %Lf\n",a,ha,hb,hc);//but it returned wrong answer so
//i used printf to check, ps: the code works with float but not with double or
//long double
ha*=3;hb*=3;hc*=3;
c=(a*ha)/hc; b=(a*ha)/hb;
ma=sqrt(0.5*b*b+0.5*c*c-0.25*a*a);
cosa=ha/ma;
r=(2*ma)/3;
l=b*(b-sqrt(a*a-hb*hb))/ha;
res=sqrt(l*l+r*r-2*cosa*l*r);
area=a*ha/2;
printf("%.3Lf %.3Lf\n",area,res);
}
system("PAUSE");
return 0;}
}
here's the input:
2
3.0 0.8660254038 0.8660254038 0.8660254038
657.8256599140 151.6154399062 213.5392629932 139.4878846649
and here what's show in the command line:
2
3.0 0.8660254038 0.8660254038 0.8660254038
3.000000 -4824911833695204400000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000.000000 284622047019579100000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000.0
00000 0.866025
-2.000 0.000
657.8256599140 151.6154399062 213.5392629932 139.4878846649
657.825660 -0.000000 28969688850499604000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000.000000 213.539263
-2.000 0.000
Press any key to continue . . .
I want to know why scanf won't take in long double in the code and how to fix it.
Thanks in advance!
Dev-c++ uses MinGW, which uses the gcc compiler and the Microsoft runtime library. Unfortunately, those components disagree on the underlying type to be used for long double (64 vs. 80 or 96 bits, I think). Windows assumes long double is the same size as double; gcc makes long double bigger.
Either choice is valid, but the combination results in a broken C and C++ implementation.
If you don't need the extra range and precision, you can read into a double and store into a long double.
Otherwise, you can write or borrow a custom string to long double converter, or just use a different implementation.
EDIT
More details:
Microsoft's own compiler and runtime library are consistent in treating long double as 64 bits, the same size as double. The language standard permits this (it requires long double to be at least as wide as double, but places the same requirements on both), but it does seem odd that it doesn't take advantage of the x86's 80-bit floating-point hardware.
gcc on x86 treats long double as 96 bits (sizeof (long double) == 12). I think only 80 of those bits are significant; the extra 16 bits are for alignment purposes.
MinGW uses gcc as its compiler, but uses Microsoft's runtime library. For most language features, this works fine, but the mismatch for long double means that you can do computations with long double, but you can't pass long double values (or pointers to them) to the runtime library. It's a bug in MinGW.
There are workarounds within MinGW. You can define the macro __USE_MINGW_ANSI_STDIO, either by passing -D__USE_MINGW_ANSI_STDIO on the gcc command line or by adding a line
#define __USE_MINGW_ANSI_STDIO
to your source files. (It has to be defined before #include <stdio.h>.) A commenter, paulsm4, says that the -ansi and -posix options cause MinGW to use its own conforming library (I have no reason to doubt this, but I'm not currently able to confirm it). Or you can call __mingw_printf() directly.
Assuming you're on Windows, Cygwin might be a good alternative (it uses gcc, but it doesn't use Microsoft's runtime library). Or you can use long double internally, but double for I/O.
You are a lucky lucky man. This won't solve the general problem of long double on MinGW, but I'll explain what is happening to your problem. Now, in a far far day when you'll be able to upvote, I want your upvote. :-) (but I don't want this to be marked as the correct response. It's the response to what you need, but not to what you asked (the general problem in your title scanf not taking in long double) ).
First, the solution: use float. Use %f in scanf/printf. The results comes perfectly equal to the ones given as the solution in your site. As a sidenote, if you want to printf with some decimals, do as it's showed in the last printf: %.10f will print 10 decimals after the decimal separator.
Second: why you had a problem with doubles: the res=sqrt() calculates a square root. Using floats, l*l+r*r-2*cosa*l*r == 0.0, using doubles it's -1.0781242565371940e-010, so something near zero BUT NEGATIVE!!! So the sqrt(-something) is NaN (Not a Number) a special value of double/float. You can check if a number is NaN by doing res != res. This because NaN != NaN (but note that this isn't guaranteed by older C standards, but in many compilers on Intel platform do it. http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html). And this explains why the printf printed something like -1.#IO.
You can avoid most of your conversion problems by actually using C++ instead of using legacy C-functions:
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
long double a = 0.0;
long double ha = 0.0;
long double hb = 0.0;
long double hc = 0.0;
int n = 0;
std::cout << "Enter Count: ";
std::cin >> n;
for (int i = 0; i < n; i++)
{
std::cout << "Enter A, Ha, Hb, Hc: ";
std::cin >> a >> ha >> hb >> hc;
std::cout.precision(10);
std::cout << "You Entered: "
<< a << " " << ha << " " << hb << " " << hc << std::endl;
ha *= 3;
hb *= 3;
hc *= 3;
long double c = (a * ha) / hc;
long double b = (a * ha) / hb;
long double ma = static_cast<long double>(std::sqrt(0.5 * b * b + 0.5 * c * c - 0.25 * a * a));
long double cosa = ha / ma;
long double r = (2 * ma) / 3;
long double l = b * (b - static_cast<long double>(std::sqrt(a * a - hb * hb))) / ha;
long double res = static_cast<long double>(std::sqrt(l * l + r * r - 2 * cosa * l * r));
long double area = a * ha / 2.0;
std::cout << "Area = " << area << std::endl;
}
return 0;
}
Don't know if this is of use to you but you could have a look at it.
long long int XDTOI(long double VALUE)
{
union
{
long double DWHOLE;
struct
{
unsigned int DMANTISSALO:32;
unsigned int DMANTISSAHI:32;
unsigned int DEXPONENT:15;
unsigned int DNEGATIVE:1;
unsigned int DEMPTY:16;
} DSPLIT;
} DKEY;
union
{
unsigned long long int WHOLE;
struct
{
unsigned int ARRAY[2];
} SPLIT;
} KEY;
int SIGNBIT,RSHIFT;
unsigned long long int BIGNUMBER;
long long int ACTUAL;
DKEY.DWHOLE=VALUE; SIGNBIT=DKEY.DSPLIT.DNEGATIVE;
RSHIFT=(63-(DKEY.DSPLIT.DEXPONENT-16383));
KEY.SPLIT.ARRAY[0]=DKEY.DSPLIT.DMANTISSALO;
KEY.SPLIT.ARRAY[1]=DKEY.DSPLIT.DMANTISSAHI;
BIGNUMBER=KEY.WHOLE;
BIGNUMBER>>=RSHIFT;
ACTUAL=((long long int)(BIGNUMBER));
if(SIGNBIT==1) ACTUAL=(-ACTUAL);
return ACTUAL;
}
Sadly enough, long double has faulty printing in GCC/Windows. However, you can guarantee that long double still does higher precision calculations in the background when you're doing arithmetic and trigonometry, because it would store at least 80 or 96 bits.
Therefore, I recommend this workaround for various things:
Use scanf on doubles, but cast them to long doubles after. You don't need precision in input parsing, anyway.
double x;
scanf("%lf", &x); // no biggie
long double y = x;
Make sure you use long double versions of functions in the <math.h> library. The normal ones will just cast your long double to double, so the higher precision will become useless.
long double sy = sqrtl(y); // not sqrt
long double ay = 2.0L * acosl(y); // note the L-suffix in the constant
To print your long double, just cast them back to double and use "%lf". Double can have at most 15 significant digits so it is more than enough. Of course, if it's not enough, you ought to switch to Linux's GCC.
printf("%.15lf\n", (double) y);
Most programs actually don't need the extra digits for the output. The thing is, even the early digits lose their precision at the slightest use of sqrt or trig functions. THEREFORE, it's OK to keep the double at least just for printing, but what's important is that you still use long double for the rough calculations to not lose the precision you worked hard to invest.