Jump to page: 1 2
Thread overview
Separate Printing Mantissa and Exponent of a Floating Point
Aug 11, 2014
Nordlöw
Aug 11, 2014
Nordlöw
Aug 11, 2014
Nordlöw
Aug 11, 2014
Justin Whear
Aug 11, 2014
Nordlöw
Aug 11, 2014
Nordlöw
Aug 13, 2014
Nordlöw
Aug 13, 2014
Nordlöw
Aug 13, 2014
Era Scarecrow
Aug 13, 2014
Nordlöw
August 11, 2014
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

instead of

1.2e3

I could of course always split on the e but that is kind of non-elegant, I believe.
August 11, 2014
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];
}
August 11, 2014
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
> 
> instead of
> 
> 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
August 11, 2014
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.
August 11, 2014
On Monday, 11 August 2014 at 15:30:30 UTC, Justin Whear wrote:
> 1. http://dlang.org/phobos/std_bitmanip.html#.FloatRep

Great! Thx.
August 11, 2014
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.
August 11, 2014
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?
August 13, 2014
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);

return to!string(sum);

/Per
August 13, 2014
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
August 13, 2014
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 about 11 to the right..

 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
}
« First   ‹ Prev
1 2