## digitalmars.D.learn - Separate Printing Mantissa and Exponent of a Floating Point

=?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
Is there a way to separately stringify/print the mantissa and
exponent of a floating point?

I want this in my pretty-printing module to produce something like

1.2 \cdot 10^3

1.2e3

I could of course always split on the e but that is kind of
non-elegant, I believe.

Aug 11 2014
=?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
Here's my current try:

string toMathML(T)(T x)  trusted /** pure */ if
(isFloatingPoint!T)
{
import std.conv: to;
import std.algorithm: findSplit; //
immutable parts = to!string(x).findSplit("e");
if (parts[2].length == 0)
return parts[0];
else
return parts[0] ~ "*10^" ~ parts[2];
}

Aug 11 2014
"Dominikus Dittes Scherkl" writes:
On Monday, 11 August 2014 at 14:15:05 UTC, Nordlöw wrote:
Here's my current try:

string toMathML(T)(T x)  trusted /** pure */ if
(isFloatingPoint!T)
{
import std.conv: to;
import std.algorithm: findSplit; //
immutable parts = to!string(x).findSplit("e");
if (parts[2].length == 0)
return parts[0];
else
return parts[0] ~ "*10^" ~ parts[2];
}

Should be patrs[1], he?

I had the same problem, but not for printing, but to do some math
on them.
Unfortunately math.h uses this internal (e.g. in trunc()) but
doesn't give it to outside.
I think it would be a good abstaction between the
hardware-realated stuff and the interface - at the moment almost
the same code is repeated three times over math.h always with the
same version switches.

Aug 11 2014
=?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Monday, 11 August 2014 at 15:37:29 UTC, Dominikus Dittes
Scherkl wrote:
Should be patrs[1], he?

No, parts[1] contains a slice to the "e" separating the mantissa
from the exponent.

Aug 11 2014
Justin Whear <justin economicmodeling.com> writes:
On Mon, 11 Aug 2014 13:47:13 +0000, Nordlöw wrote:

Is there a way to separately stringify/print the mantissa and exponent
of a floating point?

I want this in my pretty-printing module to produce something like

1.2 \cdot 10^3

1.2e3

I could of course always split on the e but that is kind of non-elegant,
I believe.

If you're writing your own pretty-printer, you can extract those pieces
using FloatRep[1] and print them however you like.

1. http://dlang.org/phobos/std_bitmanip.html#.FloatRep

Aug 11 2014
=?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Monday, 11 August 2014 at 15:30:30 UTC, Justin Whear wrote:
1. http://dlang.org/phobos/std_bitmanip.html#.FloatRep

Great! Thx.

Aug 11 2014
=?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Monday, 11 August 2014 at 15:30:30 UTC, Justin Whear wrote:
1. http://dlang.org/phobos/std_bitmanip.html#.FloatRep

I'm lacking a use case. See
http://dlang.org/library/std/bitmanip/FloatRep.html

Is unsafe

*(cast(FloatRep*)&float_instance)

the only way to use this?

Aug 11 2014
=?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Monday, 11 August 2014 at 15:30:30 UTC, Justin Whear wrote:
1. http://dlang.org/phobos/std_bitmanip.html#.FloatRep

Could someone briefly outline the algorithm that converts the
fraction part of FloatRep into a string in base 10?

My first guess is

sum = 0;

foreach (bit_index i, bit_value b; fraction)
if (b == 1)
sum += 2^^(-i);

/Per

Aug 13 2014
=?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Wednesday, 13 August 2014 at 07:51:30 UTC, Nordlöw wrote:
1. http://dlang.org/phobos/std_bitmanip.html#.FloatRep

Can somebody shortly explain why

import std.stdio, std.algorithm, std.range, std.stdio,
std.bitmanip;

void main(string args[])
{
{
float x = 1.23e10;
auto y = *cast(FloatRep*)(&x);
writeln(y.fraction, ", ",
y.exponent, ", ",
y.sign);
}

{
double x = 1.23e10;
auto y = *cast(DoubleRep*)(&x);
writeln(y.fraction, ", ",
y.exponent, ", ",
y.sign);
}
}

prints

3623111, 160, false
1945142772629504, 1056, false

Aug 13 2014
"Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Wednesday, 13 August 2014 at 07:51:30 UTC, Nordlöw wrote:
Could someone briefly outline the algorithm that converts the
fraction part of FloatRep into a string in base 10?

Walter Bright broke down the Floating point to explain how it
works and why as i recall..

http://dlang.org/d-floating-point.html
http://en.wikipedia.org/wiki/Floating_point

http://en.wikipedia.org/wiki/Single-precision_floating-point_format

As for the fraction part to floating point... You kinda have to
think in reverse. If we have say a 4 bit floating point. So...

1000 +0.5
0100 +0.25
0010 +0.125
0001 +0.0625

With this in mind you might be better off using hex, but it
depends on the application.

On Wednesday, 13 August 2014 at 07:58:40 UTC, Nordlöw wrote:
Can somebody shortly explain why it prints

3623111, 160, false
1945142772629504, 1056, false

Because they are raw int/uint types. But i'm sure that's not all
that useful...
x = 1.23e10;

so 12300000000 or 12,300,000,000 or 2DD231B00

they might make more sense in hex, but with the exponent really
just shifting where the whole/fraction parts are separated.
160-128 = it's shifted to 32/33 bits as it's starting point. and
the 1056-1024 at the 32/33 bit starting point. Same place. The
raw values they hold in hex are: 3748c7 & 0000d8000000

Let's back up then. there is 23 bits of useful data we can use,
and 34 bits present. So let's take our number and convert it to
hex

2DD231B00 and lower that until it fits in 23 bits. Or shift it

And doing this I don't get very good results to feel like I'm
helping much... I guess refer to the wiki on floating point is
probably the best you can do...

Although... I do recall seeing and having a hold of a formula
for manually printing a floating point when I was looking at raw
data before.. That formula was (don't ask where from, I don't
remember.. might be on the wiki. This is from an AHK script):

HexToFloat(d) {
Return (1-2*(d>>31)) * (2**((d>>23 & 255)-127)) * (1+(d &
8388607)/8388608) ; 2**23
}

Aug 13 2014
=?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Wednesday, 13 August 2014 at 07:58:40 UTC, Nordlöw wrote:
{
float x = 1.23e10;
auto y = *cast(FloatRep*)(&x);
writeln(y.fraction, ", ",
y.exponent, ", ",
y.sign);
}

{
double x = 1.23e10;
auto y = *cast(DoubleRep*)(&x);
writeln(y.fraction, ", ",
y.exponent, ", ",
y.sign);
}
}

It would be nice to turn these into either

- properties or at least