2
#include<stdio.h>
#include<math.h>
#define PI 2*acos(0.0)
int main(void)
{
    double theta;
    theta=tanh(1/(sqrt(3.0)));
    printf("With tanh function = %lf\n",theta);
    printf("Actual value = %lf\n",PI/6.0);
    return 0;
}

Output:

With tanh function = 0.520737

Actual value = 0.523599

Why are these two values different? It should me same as my understanding.

M.M
  • 138,810
  • 21
  • 208
  • 365
rh939
  • 55
  • 4
  • 1
    [The need for parentheses in macros in C](http://stackoverflow.com/q/10820340/995714) – phuclv Mar 03 '17 at 02:03
  • @LưuVĩnhPhúc note in this case it should evaluate to the same result – user253751 Mar 03 '17 at 02:05
  • @immibis yes I know. It's just a behavior one should get familiar with – phuclv Mar 03 '17 at 02:06
  • 2
    Neither the inaccuracy of floating-point numbers nor the missing parentheses on the macro is the problem. I calculated tanh(1/sqrt(3.0)) on an HP42S emulator and got 0.520736883716. Are you **sure** that the expected result is pi/6? – Keith Thompson Mar 03 '17 at 02:12
  • But you should definitely parenthesize your macro definition anyway: `#define PI (2*acos(0.0))`. It happens not to matter for this program because of the way you use it, but missing parentheses could cause problems in other contexts. An example: https://github.com/Keith-S-Thompson/42 – Keith Thompson Mar 03 '17 at 02:14
  • 4
    According to wolfram (http://functions.wolfram.com/ElementaryFunctions/Tanh/03/02/) tanh(πi/6) is i/sqrt(3). Here `i` is the imaginary unit (that is, the square root of -1). You can't just divide out the `i`s, and anyway you seem to be reversing tanh and atanh. I think you can deduce the identity from the identity e^iπ=-1 – rici Mar 03 '17 at 02:15
  • In what way is this result "ambiguous", as you say in the title? It's either right or it's wrong, but there's no confusion about the value. – Barmar Mar 03 '17 at 02:18
  • @AndrewLi: No, it's not a floating-point accuracy problem. – Keith Thompson Mar 03 '17 at 02:20
  • @KeithThompson Ahh yes. Thanks for the update! – Andrew Li Mar 03 '17 at 02:38

2 Answers2

6

You've got that identity completely wrong.

The actual identity is

tanh-1(i ⁄ √3) = πi ⁄ 6 (where i is the imaginary unit, √-1)

C11 can easily validate that:

#define _XOPEN_SOURCE 700
#include<stdio.h>
#include<math.h>
#include<complex.h>

int main(void)
{
    complex double theta=catanh(I/sqrt(3.0));
    printf("With atanh function = %lf\n",cimag(theta));
    printf("Actual value = %lf\n",M_PI/6);
    return 0;
}

(Live on coliru: http://coliru.stacked-crooked.com/a/f3df5358a2be67cd):

With atanh function = 0.523599
Actual value = 0.523599

M_PI will be in math.h in any Posix compliant system. Apparently, on Windows you use

#define _USE_MATH_DEFINES

but I have no idea whether Visual Studio supports complex.h.

rici
  • 234,347
  • 28
  • 237
  • 341
  • MS only writes C++ compiler and never have the intention of supporting C99 fully in Visual Studio so you have to use the [C++ ](https://msdn.microsoft.com/en-us/library/0352zzhd.aspx) header or write a [wrapper in C for your own](http://stackoverflow.com/q/1063406/995714) – phuclv Mar 04 '17 at 16:46
3

Your program has a couple of minor flaws, but none that cause it to misbehave.

Your PI macro should be parenthesized:

#define PI (2*acos(0.0))

but you happen to get away without the parentheses because of the way you use it.

The correct format for printing a double value is actually %f, but %lf is accepted as well. (%Lf is for long double. %f also works for float, because float arguments to variadic functions are promoted to double). This also doesn't affect your program's behavior.

In fact, your program is working correctly. I've confirmed using an HP 42S emulator that tanh(1/(sqrt(3.0))) is approximately 0.520737 (I get 0.520736883716).

The problem is your assumption that the result should be π/6.0. It isn't.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631