Incorrect results from C++ math library's trigonometry functions - c++

I'm currently working on a personal project that I've been doing for nearly a year now. I am trying to port it over to a Windows environment, which has succeeded. Because I am trying to get a Windows version out to people soon, I decided to continue to develop in Windows while I try to add new features and get bugs that have existed for months out. While recently attempting to add functionality which relied heavily on trigonometry, I found that all 3 trigonometric functions, oddly enough, returned the same value (1072693887) regardless of the parameter I passed. As you can imagine, this is leading to some rather strange bugs in the system.
I have math.h included, and to my knowledge no other files that would contain this function. (Perhaps there's a debugger command to find where a symbol is defined? I couldn't find any such thing, but perhaps I missed something.) I've tried asking elsewhere and searching around on Google, but to no avail...
Has anyone else heard of this problem before, or know how to fix it?

EDIT : This answer is not relevant. See comments.
This is probably due to numerical instability.
When you pass such a large value into sin(), cos(), or any of the periodic trig functions, you have to remember that there's an implicit modulo by 2*pi.
If you are using float, then the uncertainty of 1072693887, is way more than 2*pi. Therefore, whatever result you get is garbage.
We'll need to see some code to be able to see exactly what's going on though.
EDIT : Here's an illustration:
sin(1072693886) = 0.6783204666
sin(1072693887) = -0.2517863119
sin(1072693888) = -0.9504019164
But if the datatype is float, then the uncertainty of 1072693887 is +/- ~64...

1072693887 is 3FF207FF in hexadecimal, which represents 1.8908690 in IEEE single precision floating point. Are you sure your problem isn't just a representation one, ie you are casting or view the result as a integer?

All I know is that GDB is telling me the result of it is 1072693887, that it's occurring with all 3 of my trig functions (and that the arc versions of all three of them just return -1072693887) regardless of what parameter I pass.
Might be a GDB issue. What happens if you just manually print the values to the console?

Math library is fine.
You realize that the functions expect radians as input right?
E.g. :
double param = 90.0;
double rads = param * M_PI/180;
std::cout << std::fixed << "Angle : " << param << " sin : " << sin (rads) << " cos " << cos(rads);
Output :
Angle : 90.000000 sin : 1.000000 cos 0.000000-0.304811

Related

What's wrong with my algorithm?

I was resolving some online mathematics tests, and thought it's too hard to find the solutions and put it in a program on devc++, I should have
153,370,371,407,
but there was missing a solution 407.
Here is the question: The number 153 has an interesting property. In other words, it is equal to the sum of the cubes of its digits:
13 + 53 + 33 = 153
370 is another number with the same property. There are two other three-digit natural numbers with three different digits, both smaller than 500, that have the same property. Find them.
And here is my program
#include<iostream.h>
#include<math.h>
using namespace std;
int main() {
int i,nr,a,b,c;
for(i=100;i<=500;i++) {
nr=i;
c=i%10;
b=i/10%10;
a=i/10/10;
if((pow(a,3)+pow(b,3)+pow(c,3))==nr) cout<<nr<<endl;
}
system("pause");
}
Perhaps pows return double leading to floating point inaccuracy.
Instead, try
if(a*a*a + b*b*b + c*c*c == nr)
cout ....
( [EDIT] Resolved since. Mostly guessing the question from the partial code, since the question is terribly formatted at this point, and is not editable either for some reason. )
Floating point calculations are not always exact, and comparing floating point values for equality is generally ill advised.
To the point, replace
if((pow(a,3)+pow(b,3)+pow(c,3))==nr)
with
if((a*a*a + b*b*b + c*c*c) == nr)
When I run that program I get those 4 answers.
pow is never supposed to be imprecise enough to have any rounding in this trivial test.
But there seems to be a tend in questions on SO that both pull c headers into C++ and use system("pause"); that a version of pow is being used that is seriously less accurate than it ought to be. So the earlier two answers (suggesting a way to not use pow) may be effectively correct. But only because something is wrong with you math library, not because a valid copy of pow gets that bad.
So you could find a better C++ environment or better math headers, or you could start some seriously defensive programming around the flaws in your copy of pow
But if that doesn't fix it, the next thing to suspect would be endl isn't working quite correctly before that pause. Maybe you are seeing some output buffering problem. Anyway, I'm pretty sure the code is fine (even its use of pow) and the problem is in the math or I/O library functions.

CString to Float conversion

One common question ,may be I am wrong at this point but last two hours on google not give me any answer,
Question is how to convert CString to float without using std: library in c++.
I tried with wcstod() function but, This function has very different behaviour.
Please find following code,
CString Tempconvert = "32.001";
double TempConvertedValue = wcstod(Tempconvert,NULL);
So, Finally TempConvertedValue should have value 32.001. But i am getting TempConvertedValue = 32.000999999999998
Please provide me any help which convert
String "32.001" to float 32.001 only. Without using std: library.
What you see is an example of floating point internal representation. You can have a look here to see how double are stored in memory. See also this question to know why debugger shows you this value.
With this storing format, it is not possible to represent a decimal number exactly. That is why money calculations usually use special decimal types that are either custom or part of the programming language.

C++: atof() has wrong behaviour

I am using a library for loading Wavefront .obj files into my OpenGL application (tinyobjloader). I noticed that there is an error when loading objects. When I load an object with a coordinate of eg. 0.9999999 it is set to 0. By debugging I found out that the following method produces this behaviour:
static inline float parseFloat(const char*& token)
{
token += strspn(token, " \t");
float f = (float)atof(token);
token += strcspn(token, " \t\r");
return f;
}
So atof() returns somehow an int, not a float. I read that some compilers don't throw a warning when using atof() without including "stdlib.h" and the result is that atof() returns an integer.
The curious thing is that even if I include "stdlib.h" the error remains. I can't figure out what causes this behaviour.
Any idea?
The standard says to atof:
Except for the behaviour on error, it is equivalent to
strtod(nptr,(char**)NULL)
so yours returning '0' has nothing to do with a float not being able to represent it or similar.
Would you use strtod instead (which you probably should when stringstreams are not an option, just to be able to report errors), then you would likely notice that it stops parsing at the ..
This is a strong indication that you are using a locale that awaits , instead of . as s decimal separator. Depending on how your application works with locales, you might want to run it with a properly set environment variable (e.g. LC_NUMERIC=C) or do a setlocale(LC_NUMERIC,"C"); yourself before any parsing.
In any case you should analyze who in your application is using locale dependent things, and what for, so as to not collide with them. Another possible route is to require locale dependent input everywhere, so everyone needs to give the numbers to you with , as decimal separator.
You can see the documentation of atof here . Some Floating points cannot be represented in 32 bits and hence you are getting an error and value returned is zero.
//Try these
float f = 0.9999999 ;
cout << atof("0.9999999") << " " << f << endl;//output is 1 1
So what you are seeing is a valid behavior.
You may want to try strtod()

C++ decimal data types

Is there a way to use decimal data types such as decimal32, decimal64 or decimal128in my C++ programs?
The classes from the Decimal TR are not implemented for all compilers. Some compilers, e.g., gcc, implement the C Decimal TR and provide the corresponding extensions in C++, too. In the past there was an open source implementation for the C++ Decimal TR available but I failed to locate it. If your compiler doesn't support the decimal types, your best option is probably to create a wrapper for IBM's decNumber library.
To improve the situation in the future of C++, I have created a plan to update the TR and I'm going to turn the current TR into a complete proposal ready for the next C++ committee meeting (in April in Bristol), trying to get it adopted into the C++ standard, possibly into the revision planned for 2014. The implementation I have is part of my regular work and it isn't up to me to decide whether it is can be made available publically although there is some hope that it can be open sourced at some point.
You can use easy to use header-only solution for C++ with templates:
https://github.com/vpiotr/decimal_for_cpp
Notice that this is not a *Big*Decimal class; it is limited to 64 bits' worth of "mantissa" digits.
[taken from link]
#include "decimal.h"
using namespace dec;
// the following declares currency variable with 2 decimal points
// initialized with integer value (can be also floating-point)
decimal<2> value(143125);
// to use non-decimal constants you need to convert them to decimal
value = value / decimal_cast<2>(333.0);
// output values
cout << "Result is: " << value << endl;
// this should display something like "429.80"
// to mix decimals with different precision use decimal_cast
decimal<6> exchangeRate(12.1234);
value = decimal_cast<2>(decimal_cast<6>(value) * exchangeRate);
cout << "Result 2 is: " << value << endl;
// this should display something like "5210.64"
cout << "Result 2<6> is: " << decimal_cast<6>(value) << endl;
// this should display something like "5210.640000"
use an int32 or int64, and (manually) shift the decimal point to where you want it to be. If you're measuring dollars, for example, just measure cents instead and display the value differently. simple!
Boost has cpp_dec_float as well. That's probably the best solution until it's adopted into the standard.
https://www.boost.org/doc/libs/1_68_0/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/cpp_dec_float.html
EDIT: This library uses floating point values in the implementation so is not a true decimal math library IMO.
gcc/clang (usually) come with their own floating point decimal implementations, if your distro decides to compile them into whatever gcc/clang version they offer (not the case for some arm distros I tried out). This is why you sometimes need a custom decimal type implementation. Try mine for ideas (tested on i586 all the way to aarch64).
decimal.h this library is not exit is is saying by my compiler.
/tmp/TQDyfEvEXQ.cpp:2:10: fatal error: decimal.h: No such file or directory
2 | #include <decimal.h>
| ^~~~~~~~~~~
compilation terminated.```

Understanding floating point variables and operators in c++ (Also a possible book error)

I am working through a beginning C++ class and my book(Starting Out with C++ Early Objects 7th edition) has a very poor example of how to check the value of a floating point variable.
The book example in question(filename pr4-04.cpp):
// This program demonstrates how to safely test a floating-point number
// to see if it is, for all practical purposes, equal to some value.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double result = .666667 * 6.0;
// 2/3 of 6 should be 4 and, if you print result, 4 is displayed.
cout << "result = " << result << endl;
// However, internally result is NOT precisely equal to 4.
// So test to see if it is "close" to 4.
if (abs(result - 4.0 < .0001))
cout << "result DOES equal 4!" << endl;
else
cout << "result DOES NOT equal 4!" << endl;
return 0;
}
And I use g++ in Ubuntu to compile my code like this:
g++ pr4-04.cpp -o pr4-04 && ./pr4-04
And I get this error:
error: call of overloaded ‘abs(bool)’ is ambiguous
I am able to fix this by changing abs() to fabs(), but this is still super confusing! Why is the book giving us things which won't compile, or is this just me? Why does the cout of 'result' give 4 instead of 4.000002? Why does this value seem to change when it is used in the if{} statement?
I get that we can't just use == to check for equivalence, but why do I need to use the absolute value? I get the same answer whether or not I use it. So what is the point?
Not to mention, this seems like a very poor way to check for floating point equivalence. Is there a better way to do this? This topic seems awfully important.
I found this topic here on stackoverflow, but their solution:
fabs(f1 - f2) < precision-requirement
fabs(f1 - f2) < max(fabs(f1), fabs(f2)) * percentage-precision-requirement
Doesn't make much sense to me in the context of my 4 chapters worth of C++ experience. I would greatly appreciate some help. Our book has given me a whopping 6 sentences of text to explain all of this.
Edit: As suggested by some I tried to find an errata page, but after 30mins of searching the textbook, internet, and my course website I was only able to find this downloadable zip file, which required a login -_-
I also copied the code perfectly. That was not MY typo, I copied it directly from a CD with the code on it. It is also typed that way in the book.
if (abs(result - 4.0 < .0001))
The parenthesis are wrong, you probably mean: if (abs(result-4.0) < .0001).
As to why it did not compile, the standard determines in §26.8p8 that
In addition to the double versions of the math functions in , C++ adds float and long double overloaded versions of these functions, with the same semantics.
The expression (result-4.0 < .0001) yields a bool, and there is no overload of abs that takes a bool argument, but there are multiple versions of abs for which the argument is implicitly convertible from bool. The compiler does not find one of the conversion sequences better than the rest and bails out with the ambiguity error.
The problem is clearly the line
if (abs(result - 4.0 < .0001))
which should be written as
if (abs(result - 4.0) < .0001)
I would assume that this is a simple typo. Report the error to the author of the book!
BTW, the original code does compile on my system without any problem, giving the expected result! That is, even if the author tested the code he may not have noticed that it is problematic!
Also answering the question on why abs() is needed: some decimal numbers are rounded to a floating point value which is slightly smaller than the expected result while others are rounded to number which are slightly bigger. In which direction the values are round (if at all: some decimal numbers can be represented exactly using binary floating points) is somewhat hard to predict. Thus, the result may be slightly bigger or slightly smaller than the expectation and the difference, thus, positive or negative, respectively.