Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #66185 > unrolled thread

Floating point to string, and back via `%a'...

Started by"Chris M. Thomasson" <nospam@nospam.nospam>
First post2015-07-22 12:46 -0700
Last post2015-07-24 11:47 -0700
Articles 11 on this page of 31 — 7 participants

Back to article view | Back to comp.lang.c


Contents

  Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 12:46 -0700
    Re: Floating point to string, and back via `%a'... James Kuyper <jameskuyper@verizon.net> - 2015-07-22 16:19 -0400
      Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 13:49 -0700
        Re: Floating point to string, and back via `%a'... Keith Thompson <kst-u@mib.org> - 2015-07-22 14:01 -0700
        Re: Floating point to string, and back via `%a'... James Kuyper <jameskuyper@verizon.net> - 2015-07-22 17:18 -0400
          Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 14:22 -0700
    Re: Floating point to string, and back via `%a'... Keith Thompson <kst-u@mib.org> - 2015-07-22 13:40 -0700
      Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 14:01 -0700
        Re: Floating point to string, and back via `%a'... Keith Thompson <kst-u@mib.org> - 2015-07-22 14:12 -0700
          Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 14:20 -0700
            Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 14:24 -0700
            Re: Floating point to string, and back via `%a'... glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-07-22 21:30 +0000
              Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 14:39 -0700
            Re: Floating point to string, and back via `%a'... Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2015-07-22 19:49 -0600
    Re: Floating point to string, and back via `%a'... Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-22 22:28 +0100
      Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 14:34 -0700
        Re: Floating point to string, and back via `%a'... Keith Thompson <kst-u@mib.org> - 2015-07-22 14:58 -0700
          Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 15:43 -0700
          Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 15:45 -0700
          Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 15:51 -0700
            Re: Floating point to string, and back via `%a'... Robert Wessel <robertwessel2@yahoo.com> - 2015-07-22 18:21 -0500
              Re: Floating point to string, and back via `%a'... Keith Thompson <kst-u@mib.org> - 2015-07-22 16:58 -0700
          Re: Floating point to string, and back via `%a'... Keith Thompson <kst-u@mib.org> - 2015-07-22 16:52 -0700
          Re: Floating point to string, and back via `%a'... Keith Thompson <kst-u@mib.org> - 2015-07-22 17:08 -0700
        Re: Floating point to string, and back via `%a'... Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-23 00:01 +0100
          Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-22 19:40 -0700
            Re: Floating point to string, and back via `%a'... Keith Thompson <kst-u@mib.org> - 2015-07-22 22:32 -0700
            Re: Floating point to string, and back via `%a'... Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-23 11:07 +0100
              Re: Floating point to string, and back via `%a'... Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-23 11:25 +0100
                Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-24 11:44 -0700
              Re: Floating point to string, and back via `%a'... "Chris M. Thomasson" <nospam@nospam.nospam> - 2015-07-24 11:47 -0700

Page 2 of 2 — ← Prev page 1 [2]


#66220

FromRobert Wessel <robertwessel2@yahoo.com>
Date2015-07-22 18:21 -0500
Message-ID<1a90raht141tr0c3kvkafnvrvqqf8s1qov@4ax.com>
In reply to#66217
On Wed, 22 Jul 2015 15:51:54 -0700, "Chris M. Thomasson"
<nospam@nospam.nospam> wrote:

>> "Keith Thompson"  wrote in message 
>> news:lnfv4f26t4.fsf@kst-u.example.com...
>
>[...]
>> What output do you get using MSVC?  If it's significantly different,
>> there may well be a bug in MSVC (presumably in its runtime library).
>
>I get with with MING 4.8 on windows:
>_________________________________________
>in  = 1.0123456789 = 0x1.032916p+0
>buf = "0x1.032916p+0"
>sscanf returned 0
>out = 0.0000000000 = 0x0.000000p+0
>in != out
>_________________________________________
>
>So, the nasty problem has to be in ms runtime shi%.
>
>Damn!  ;^( 


From the MSDN VS 2015 scanf types page:

"The a and A specifiers (see printf Type Field Characters) are not
available with scanf."

https://msdn.microsoft.com/en-us/library/6ttkkkhh.aspx

[toc] | [prev] | [next] | [standalone]


#66223

FromKeith Thompson <kst-u@mib.org>
Date2015-07-22 16:58 -0700
Message-ID<lnzj2nzqwh.fsf@kst-u.example.com>
In reply to#66220
Robert Wessel <robertwessel2@yahoo.com> writes:
> On Wed, 22 Jul 2015 15:51:54 -0700, "Chris M. Thomasson"
> <nospam@nospam.nospam> wrote:
>
>>> "Keith Thompson"  wrote in message 
>>> news:lnfv4f26t4.fsf@kst-u.example.com...
>>
>>[...]
>>> What output do you get using MSVC?  If it's significantly different,
>>> there may well be a bug in MSVC (presumably in its runtime library).
>>
>>I get with with MING 4.8 on windows:
>>_________________________________________
>>in  = 1.0123456789 = 0x1.032916p+0
>>buf = "0x1.032916p+0"
>>sscanf returned 0
>>out = 0.0000000000 = 0x0.000000p+0
>>in != out
>>_________________________________________
>>
>>So, the nasty problem has to be in ms runtime shi%.
>>
>>Damn!  ;^( 
>
>
> From the MSDN VS 2015 scanf types page:
>
> "The a and A specifiers (see printf Type Field Characters) are not
> available with scanf."
>
> https://msdn.microsoft.com/en-us/library/6ttkkkhh.aspx

Well there it is -- and that's why sscanf is returning 0.

The purpose of "%a" is to have a realtively simple way to convert a
floating-point number to a string without loss of precision.

Using "%g" with a large precision, such as "%.64g", will likely achieve
the same result, but not as reliably.  Or you can borrow code from an
open source implementation of scanf.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#66222

FromKeith Thompson <kst-u@mib.org>
Date2015-07-22 16:52 -0700
Message-ID<ln4mkv21jc.fsf@kst-u.example.com>
In reply to#66210
Keith Thompson <kst-u@mib.org> writes:
> "Chris M. Thomasson" <nospam@nospam.nospam> writes:
> [...]
>>> It looks like MSVC simply has a bug.  You could calculate the number of
>>> digits you need but that would be fiddly to get right in every single
>>> case.
>>
>> Right. FWIW, %a does not work on MSVC for sscanf always returns zero.
>
> Does MSVC just not implement %a?  Did you try changing to %la (you may
> have already answered that).
>
> Try this test program:
>
> #include <stdio.h>
> int main(void) {
>     char buf[256];
>     double in  = 1.0123456789;
>     double out = 1.0123456789;

Sorry, I should have left `out` uninitialized, or initialized it
to some other value (it was a copy-and-paste error).

>         int result;
>
>         sprintf(buf, "%a", in);
>         result = sscanf(buf, "%la", &out);
>
>         printf("in  = %.10f = %a\n", in, in);
>         printf("buf = \"%s\"\n", buf);
>         printf("sscanf returned %d\n", result);
>         printf("out = %.10f = %a\n", out, out);
>
>         if (in == out) {
>                 puts("in == out");
>         }
>         else {
>                 puts("in != out");
>         }
>         return 0;
> }
[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#66224

FromKeith Thompson <kst-u@mib.org>
Date2015-07-22 17:08 -0700
Message-ID<lnvbdbzqff.fsf@kst-u.example.com>
In reply to#66210
Keith Thompson <kst-u@mib.org> writes:
> "Chris M. Thomasson" <nospam@nospam.nospam> writes:
> [...]
>>> It looks like MSVC simply has a bug.  You could calculate the number of
>>> digits you need but that would be fiddly to get right in every single
>>> case.
>>
>> Right. FWIW, %a does not work on MSVC for sscanf always returns zero.
>
> Does MSVC just not implement %a?  Did you try changing to %la (you may
> have already answered that).
>
> Try this test program:
>
> #include <stdio.h>
> int main(void) {
>     char buf[256];
>     double in  = 1.0123456789;
>     double out = 1.0123456789;
>         int result;
>
>         sprintf(buf, "%a", in);
>         result = sscanf(buf, "%la", &out);
>
>         printf("in  = %.10f = %a\n", in, in);
>         printf("buf = \"%s\"\n", buf);
>         printf("sscanf returned %d\n", result);
>         printf("out = %.10f = %a\n", out, out);
>
>         if (in == out) {
>                 puts("in == out");
>         }
>         else {
>                 puts("in != out");
>         }
>         return 0;
> }

Here's a better version.  It doesn't examine the value of `out` unless
sscanf succeeds.

#include <stdio.h>
#include <float.h>
int main(void) {
    char buf[256];
    double in  = 1.0123456789;
    double out = FLT_MAX; /* arbitrary value */
    int result;

    sprintf(buf, "%a", in);
    result = sscanf(buf, "%la", &out);

    printf("in  = %.50f = %a\n", in, in);
    printf("buf = \"%s\"\n", buf);
    printf("sscanf returned %d\n", result);
    if (result == 1) {
        printf("out = %.50f = %a\n", out, out);
        if (in == out) {
            puts("in == out");
        }
        else {
            puts("in != out");
        }
    }
    return 0;
}

> On my system, the output is:
>
> in  = 1.0123456789 = 0x1.0329161f1f56cp+0
> buf = "0x1.0329161f1f56cp+0"
> sscanf returned 1
> out = 1.0123456789 = 0x1.0329161f1f56cp+0
> in == out
>
> What output do you get using MSVC?  If it's significantly different,
> there may well be a bug in MSVC (presumably in its runtime library).

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#66218

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-07-23 00:01 +0100
Message-ID<87h9ov4x0f.fsf@bsb.me.uk>
In reply to#66208
"Chris M. Thomasson" <nospam@nospam.nospam> writes:
<snip>
> Right. FWIW, %a does not work on MSVC for sscanf always returns zero.

It's %la for sscanf (I'm sure I've seen that mentioned already).  If
that returns zero, things are much worse than I thought.

> So, I am going to use %lf and stick to a precision of %.10 for now. I
>do not care if the double to string back to double conversion looses
>precision because the fractal can be generated on the end result of the
>conversion, not the original double.

If that works, OK, but it sounds odd.  Fractals are often very sensitive
to initial conditions, but I've not seen how these numbers are used.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#66230

From"Chris M. Thomasson" <nospam@nospam.nospam>
Date2015-07-22 19:40 -0700
Message-ID<mopk6n$i8k$1@speranza.aioe.org>
In reply to#66218
>"Ben Bacarisse"  wrote in message news:87h9ov4x0f.fsf@bsb.me.uk... 

>>"Chris M. Thomasson" <nospam@nospam.nospam> writes:
<snip>
>> Right. FWIW, %a does not work on MSVC for sscanf always returns zero.

>It's %la for sscanf (I'm sure I've seen that mentioned already).  If
>that returns zero, things are much worse than I thought.

Unfortunately, it returns zero. It's just not going to work 
with MSVC or MINGW on Windows.

;^(


>>So, I am going to use %lf and stick to a precision of %.10 for now. I
>>do not care if the double to string back to double conversion looses
>>precision because the fractal can be generated on the end result of the
>>conversion, not the original double.

>If that works, OK, but it sounds odd.  Fractals are often very sensitive
>to initial conditions, but I've not seen how these numbers are used.

It should work. Here is a simple scenario that I am hoping works 
out...

Lets say Alice gets a number that is part of the public key 
generated from the cleartext she just typed in on here computer: 
1.0123456789

Alice then runs it through a local round trip from double-to-
string-to-double, and gets back:

1.0123456

Fine... Alice then uses this new value for the public key, 
generates the fractal cipher based on the private key, encrypts 
the cleartext and sends both 1.0123456 and the ciphertext across
the wire to Bob.

Bob converts the public key string to a double. I am HOPING that 
Bob gets exactly:

1.0123456

If Alice and Bob are using a std floating point representation 
(e.g., IEEE).

Shi% should hit the fan if Bob cannot get this string to convert 
into 1.0123456! The fractal that Bob creates should be using  
1.0123456 damn it!  ;^/

Assume that both Bob and Alice are using a program compiled with 
the same compiler, have different archs but still use the same 
floating point standard that the program depends on.

What can possibly go wrong Ben?!

Tick, tick, tick... What is that? Oh, well, now I hear a bang and 
see a lot of fire with many fierce looking demons disseminating 
from it!

Oh shi%!

;^O

[toc] | [prev] | [next] | [standalone]


#66231

FromKeith Thompson <kst-u@mib.org>
Date2015-07-22 22:32 -0700
Message-ID<lnr3nzzbf7.fsf@kst-u.example.com>
In reply to#66230
"Chris M. Thomasson" <nospam@nospam.nospam> writes:
[...]
> Bob converts the public key string to a double. I am HOPING that 
> Bob gets exactly:
>
> 1.0123456

Unless you're using decimal floating-point (which you very probably
aren't), it's not possible to get exactly 1.0123456.

The closest you can get in IEEE double precision is
1.0123455999999999566085762126022018492221832275390625

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#66240

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-07-23 11:07 +0100
Message-ID<87bnf3427q.fsf@bsb.me.uk>
In reply to#66230
"Chris M. Thomasson" <nospam@nospam.nospam> writes:
<snip>
>>>So, I am going to use %lf and stick to a precision of %.10 for now. I
>>>do not care if the double to string back to double conversion looses
>>>precision because the fractal can be generated on the end result of the
>>>conversion, not the original double.
>
>>If that works, OK, but it sounds odd.  Fractals are often very sensitive
>>to initial conditions, but I've not seen how these numbers are used.
>
> It should work. Here is a simple scenario that I am hoping works
> out...
>
> Lets say Alice gets a number that is part of the public key generated
> from the cleartext she just typed in on here computer: 1.0123456789
>
> Alice then runs it through a local round trip from double-to-
> string-to-double, and gets back:
>
> 1.0123456
>
> Fine... Alice then uses this new value for the public key, generates
> the fractal cipher based on the private key, encrypts the cleartext
> and sends both 1.0123456 and the ciphertext across
> the wire to Bob.
>
> Bob converts the public key string to a double. I am HOPING that Bob
> gets exactly:
>
> 1.0123456

You can't be sure of that but it's very, very likely.  For one thing,
you seem to be deliberately not using the full precision which makes it
much more likely that the conversion will produce the same result.  Mind
you, that is limiting your key space.  But:

> If Alice and Bob are using a std floating point representation (e.g.,
> IEEE).

If you can assume that Alice and Bob are using the same floating point
format then you can simply transmit the bits in an address agnostic
manner.

In a conforming C implementation, you can check if double is the
expected format (again barring byte ordering) by testing the macro
__STDC_IEC_559__, but I don't know if MSVC conforms in this regard.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#66243

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-07-23 11:25 +0100
Message-ID<87380f41c9.fsf@bsb.me.uk>
In reply to#66240
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> "Chris M. Thomasson" <nospam@nospam.nospam> writes:
<snip>
>> Alice then runs it through a local round trip from double-to-
>> string-to-double, and gets back:
>>
>> 1.0123456
>>
>> Fine... Alice then uses this new value for the public key, generates
>> the fractal cipher based on the private key, encrypts the cleartext
>> and sends both 1.0123456 and the ciphertext across
>> the wire to Bob.
>>
>> Bob converts the public key string to a double. I am HOPING that Bob
>> gets exactly:
>>
>> 1.0123456
>
> You can't be sure of that but it's very, very likely.  For one thing,
> you seem to be deliberately not using the full precision which makes it
> much more likely that the conversion will produce the same result.

Reading Keith's reply has reminded me that I'm not being clear about the
distinction between internal and external representations.  Most likely,
neither Alice nor Bob have 1.0123456 exactly.  What you can hope for
(and it's only a hope) is that those decimal digits translate to the
same binary floating point number that Alice had to start with.

As has been suggested elsewhere, if your numbers are always in some
well-known range you might try using integers instead.  Also, look at
the functions frexp and scalbn.  You can use these to simulate the
effect of the %s format that you've found you can't rely on:

     int exp;
     double d = frexp(1.0123456, &exp);
     printf("%a %d %llx\n", d, exp, (long long unsigned)scalbn(d, 53));

Produces

  0x1.032914cc3fdf1p-1 1 1032914cc3fdf1

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#66300

From"Chris M. Thomasson" <nospam@nospam.nospam>
Date2015-07-24 11:44 -0700
Message-ID<mou12o$sp2$1@speranza.aioe.org>
In reply to#66243
> "Ben Bacarisse"  wrote in message news:87380f41c9.fsf@bsb.me.uk... 

> > Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> >> "Chris M. Thomasson" <nospam@nospam.nospam> writes:
<snip>
> >> Alice then runs it through a local round trip from double-to-
> >> string-to-double, and gets back:
> >>
> >> 1.0123456
> >>
> >> Fine... Alice then uses this new value for the public key, generates
> >> the fractal cipher based on the private key, encrypts the cleartext
> >> and sends both 1.0123456 and the ciphertext across
> >> the wire to Bob.
> >>
> >> Bob converts the public key string to a double. I am HOPING that Bob
> >> gets exactly:
> >>
> >> 1.0123456
> >> 
> > You can't be sure of that but it's very, very likely.  For one thing,
> > you seem to be deliberately not using the full precision which makes it
> > much more likely that the conversion will produce the same result.

I thought this just might be the case here Ben.


> Reading Keith's reply has reminded me that I'm not being clear about the
> distinction between internal and external representations.  Most likely,
> neither Alice nor Bob have 1.0123456 exactly.  What you can hope for
> (and it's only a hope) is that those decimal digits translate to the
> same binary floating point number that Alice had to start with.

Exactly Right for that is the hope I am hoping for!

;^o


> As has been suggested elsewhere, if your numbers are always in some
> well-known range you might try using integers instead.  Also, look at
> the functions frexp and scalbn.  You can use these to simulate the
> effect of the %s format that you've found you can't rely on:

>      int exp;
>      double d = frexp(1.0123456, &exp);
>      printf("%a %d %llx\n", d, exp, (long long unsigned)scalbn(d, 53));

> Produces

>   0x1.032914cc3fdf1p-1 1 1032914cc3fdf1


Nice! Thank you so much for the excellent information Ben, and everyone 
else!

:^D

[toc] | [prev] | [next] | [standalone]


#66301

From"Chris M. Thomasson" <nospam@nospam.nospam>
Date2015-07-24 11:47 -0700
Message-ID<mou19c$tb8$1@speranza.aioe.org>
In reply to#66240
>"Ben Bacarisse"  wrote in message news:87bnf3427q.fsf@bsb.me.uk...

>"Chris M. Thomasson" <nospam@nospam.nospam> writes:
[...]
>You can't be sure of that but it's very, very likely.  For one thing,
>you seem to be deliberately not using the full precision which makes it
>much more likely that the conversion will produce the same result.  Mind
>you, that is limiting your key space.  But:

Yeah. I know it is limiting the key space, however I am thinking that 
something
like %.13 is going to be good enough. Thank god this is only a toy program!

;^)


>> If Alice and Bob are using a std floating point representation (e.g.,
>> IEEE).

>If you can assume that Alice and Bob are using the same floating point
>format then you can simply transmit the bits in an address agnostic
>manner.

>In a conforming C implementation, you can check if double is the
>expected format (again barring byte ordering) by testing the macro
>__STDC_IEC_559__, but I don't know if MSVC conforms in this regard.

Now this is going to be useful Ben.

Thanks again!

:^D

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.c


csiph-web