1

so I just started experimenting with C#. I have one line of code and the output is a "?".

Code: Console.WriteLine(Math.Pow(Math.Exp(1200), 0.005d));

Output: ?

I am using Visual Studio and it also says exited with code 0.

It should output 403.4287934927351. I also tried it out with Geogebra and it's correct as shown in the image so it's not infinity. image representing clamation

Marci
  • 57
  • 8
  • Because it's trying to print out the infinity symbol, I'd imagine. – Matthew Watson Nov 20 '20 at 09:37
  • That's correct. You can configure your terminal to support Unicode characters, [see here](https://stackoverflow.com/questions/5750203/how-to-write-unicode-characters-to-the-console) – canton7 Nov 20 '20 at 09:38
  • Does this answer your question? [How to write Unicode characters to the console?](https://stackoverflow.com/questions/5750203/how-to-write-unicode-characters-to-the-console) – Cleptus Nov 20 '20 at 09:39
  • 1
    By the way, this prints `true`: `Console.WriteLine(double.IsInfinity(Math.Exp(1200)));` – Matthew Watson Nov 20 '20 at 09:39
  • Add the following to the start of your console app: `Console.OutputEncoding = System.Text.Encoding.Unicode;` – Matthew Watson Nov 20 '20 at 09:40
  • Probably you are confused as to why this returns infinity. That's because `Math.Exp(1200)` is too big number to be stored in a `double`, so already here it returns special "number" representing infinity, and from that point on all calculations just return infinity. – Evk Nov 20 '20 at 09:40
  • It's worth noting that .NET 5 changed the output for `double.Infinity` from `Infinity` to `∞`, as a side-effect of moving from NLS to ICU for localization (on Windows at least -- other platforms have always used ICU) – canton7 Nov 20 '20 at 09:41
  • @canton7 but docs say that Infinity.ToString() returns `CultureInfo.NumberFormat.PositiveInfinitySymbol` (or negative infinity symbol) already. – Evk Nov 20 '20 at 09:46
  • @Evk Indeed, and `NumberFormat.PositiveInfinitySymbol` (which used to be sourced from NLS, and is now sourced from ICU) changed from `Infinity` to `∞` (for the main cultures, at least). The invariant culture still uses `Infinity`, though: that's hard-coded and isn't sourced from ICU – canton7 Nov 20 '20 at 09:47
  • Ah, I guess my culture is not "main" then, since it alerady has this symbol as ∞ – Evk Nov 20 '20 at 09:49
  • Which target framework is used? [.NET fiddle](https://dotnetfiddle.net/FLHZJ8) shows `Infinity` or `∞` symbol in output – Pavel Anikhouski Nov 20 '20 at 09:51

1 Answers1

3

C# double type (which is returned by Math.Exp function) is a fixed-size type (64 bits), and so it cannot represent arbitrary large numbers. Largest number it can represent is double.MaxValue constant, and it's of order 10^308, which is less than what you are trying to compute (e^2000).

When result of computation exceeds maximum representable value - special "number" representing Infinity is returned. So

double x = Math.Exp(1200); // cannot represent this with double type
bool isInifinite = double.IsInfinity(x); // true

After you got this "infinity" - all other computations involving it will just return infinity back, there is nothing else they can do. So then whole expression Math.Pow(Math.Exp(1200), 0.005d)) returns "infinity".

When you try to write result to console, it gets converted to string. The rules for converting mentioned infinity to string are as follows:

Regardless of the format string, if the value of a Single or Double floating-point type is positive infinity, negative infinity, or not a number (NaN), the formatted string is the value of the respective PositiveInfinitySymbol, NegativeInfinitySymbol, or NaNSymbol property that is specified by the currently applicable NumberFormatInfo object.

In your current culture, PositiveInfinitySymbol is likely "∞", but your console encoding likely cannot represent this symbol, so it outputs "?". You can change console encoding to UTF8 like this:

Console.OutputEncoding = Encoding.UTF8;

And then it will show "∞" correctly.

There is no framework-provided type to work with arbitrary sized rational numbers, as far as I know. For integer there is BigInteger type though.

In this specific case you can do fine with just double, because you can do the same thing with:

Console.WriteLine(Math.Exp(1200 * 0.005d));
// outputs 403.4287934927351

Now there are no intermediate results exceeding capacity of double, and so it works fine.

For cases where it's not possible - there are third party libraries which allow to work with arbitrary large rationals.

Evk
  • 98,527
  • 8
  • 141
  • 191