Explicit specification of the double precision representation used by compiler
up vote
4
down vote
favorite
I've recently come across the problem that visual-c++
does not seem to be IEEE 754 compliant, but instead uses subnormal representation. That is, double precision floats in it do not have the usual representation of 1 sign bit, 11 exponent bits and 52 explicitly stored significant decimal bits, see below.
As gcc
and clang
are however compliant and consistent cross-platform behaviour is highly desired I would like to know whether it is possible to force visual-c++
to use the normal representation. Alternatively making gcc
and clang
use the subnormal representation would of course also solve the problem.
The issue of the different double representations can be reproduced in visual-c++
, gcc
and clang
using the following code:
#include <iostream>
#include <string>
int main()
{
try {
std::stod("8.0975711886543594e-324");
std::cout << "Subnormal representation.";
} catch (std::exception& e) {
std::cout << "Normal representation.";
}
return 0;
}
Is a representation specification to produce consitent behaviour in all three cases at all possible?
Edit: As geza pointed out, this appears a problem in the different implementations of std::stod
, which would then make the question if there is any way to make std::stod
behave consistently without having to implement a seperate wrapper for it.
c++ gcc visual-c++ clang
|
show 1 more comment
up vote
4
down vote
favorite
I've recently come across the problem that visual-c++
does not seem to be IEEE 754 compliant, but instead uses subnormal representation. That is, double precision floats in it do not have the usual representation of 1 sign bit, 11 exponent bits and 52 explicitly stored significant decimal bits, see below.
As gcc
and clang
are however compliant and consistent cross-platform behaviour is highly desired I would like to know whether it is possible to force visual-c++
to use the normal representation. Alternatively making gcc
and clang
use the subnormal representation would of course also solve the problem.
The issue of the different double representations can be reproduced in visual-c++
, gcc
and clang
using the following code:
#include <iostream>
#include <string>
int main()
{
try {
std::stod("8.0975711886543594e-324");
std::cout << "Subnormal representation.";
} catch (std::exception& e) {
std::cout << "Normal representation.";
}
return 0;
}
Is a representation specification to produce consitent behaviour in all three cases at all possible?
Edit: As geza pointed out, this appears a problem in the different implementations of std::stod
, which would then make the question if there is any way to make std::stod
behave consistently without having to implement a seperate wrapper for it.
c++ gcc visual-c++ clang
1
Here, the difference lies instd::stod
, doesn't it? GCC and clang throw out_of_range for subnormal numbers (which is weird, if you ask me), while msvc doesn't. I even don't understand, why they throw out_of_range for a small number which is truncated to zero. It's definitely not out_of_range. There should be a separate exception for this case.
– geza
Nov 19 at 13:39
Relevant: stackoverflow.com/questions/48086830/…
– geza
Nov 19 at 13:45
1
std::stod
is badly designed.strtod
can report whether the ERANGE means overflow or underflow.std::stod
cannot.
– geza
Nov 19 at 13:48
@geza Thanks, edited the post to reflect that itsstd::stod
, maybe there's some standard way around the design
– abcalphabet
Nov 19 at 13:49
Yes, usestrtod
, which doesn't have this limitation. It behaves not as documented for subnormal numbers: it will return the subnormal value (so, contrary to the doc, it returns a non-zero value, yet sets errno=ERANGE). Which is good for us, because you can get the number you want.
– geza
Nov 19 at 13:53
|
show 1 more comment
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I've recently come across the problem that visual-c++
does not seem to be IEEE 754 compliant, but instead uses subnormal representation. That is, double precision floats in it do not have the usual representation of 1 sign bit, 11 exponent bits and 52 explicitly stored significant decimal bits, see below.
As gcc
and clang
are however compliant and consistent cross-platform behaviour is highly desired I would like to know whether it is possible to force visual-c++
to use the normal representation. Alternatively making gcc
and clang
use the subnormal representation would of course also solve the problem.
The issue of the different double representations can be reproduced in visual-c++
, gcc
and clang
using the following code:
#include <iostream>
#include <string>
int main()
{
try {
std::stod("8.0975711886543594e-324");
std::cout << "Subnormal representation.";
} catch (std::exception& e) {
std::cout << "Normal representation.";
}
return 0;
}
Is a representation specification to produce consitent behaviour in all three cases at all possible?
Edit: As geza pointed out, this appears a problem in the different implementations of std::stod
, which would then make the question if there is any way to make std::stod
behave consistently without having to implement a seperate wrapper for it.
c++ gcc visual-c++ clang
I've recently come across the problem that visual-c++
does not seem to be IEEE 754 compliant, but instead uses subnormal representation. That is, double precision floats in it do not have the usual representation of 1 sign bit, 11 exponent bits and 52 explicitly stored significant decimal bits, see below.
As gcc
and clang
are however compliant and consistent cross-platform behaviour is highly desired I would like to know whether it is possible to force visual-c++
to use the normal representation. Alternatively making gcc
and clang
use the subnormal representation would of course also solve the problem.
The issue of the different double representations can be reproduced in visual-c++
, gcc
and clang
using the following code:
#include <iostream>
#include <string>
int main()
{
try {
std::stod("8.0975711886543594e-324");
std::cout << "Subnormal representation.";
} catch (std::exception& e) {
std::cout << "Normal representation.";
}
return 0;
}
Is a representation specification to produce consitent behaviour in all three cases at all possible?
Edit: As geza pointed out, this appears a problem in the different implementations of std::stod
, which would then make the question if there is any way to make std::stod
behave consistently without having to implement a seperate wrapper for it.
c++ gcc visual-c++ clang
c++ gcc visual-c++ clang
edited Nov 19 at 13:49
asked Nov 19 at 13:21
abcalphabet
4081213
4081213
1
Here, the difference lies instd::stod
, doesn't it? GCC and clang throw out_of_range for subnormal numbers (which is weird, if you ask me), while msvc doesn't. I even don't understand, why they throw out_of_range for a small number which is truncated to zero. It's definitely not out_of_range. There should be a separate exception for this case.
– geza
Nov 19 at 13:39
Relevant: stackoverflow.com/questions/48086830/…
– geza
Nov 19 at 13:45
1
std::stod
is badly designed.strtod
can report whether the ERANGE means overflow or underflow.std::stod
cannot.
– geza
Nov 19 at 13:48
@geza Thanks, edited the post to reflect that itsstd::stod
, maybe there's some standard way around the design
– abcalphabet
Nov 19 at 13:49
Yes, usestrtod
, which doesn't have this limitation. It behaves not as documented for subnormal numbers: it will return the subnormal value (so, contrary to the doc, it returns a non-zero value, yet sets errno=ERANGE). Which is good for us, because you can get the number you want.
– geza
Nov 19 at 13:53
|
show 1 more comment
1
Here, the difference lies instd::stod
, doesn't it? GCC and clang throw out_of_range for subnormal numbers (which is weird, if you ask me), while msvc doesn't. I even don't understand, why they throw out_of_range for a small number which is truncated to zero. It's definitely not out_of_range. There should be a separate exception for this case.
– geza
Nov 19 at 13:39
Relevant: stackoverflow.com/questions/48086830/…
– geza
Nov 19 at 13:45
1
std::stod
is badly designed.strtod
can report whether the ERANGE means overflow or underflow.std::stod
cannot.
– geza
Nov 19 at 13:48
@geza Thanks, edited the post to reflect that itsstd::stod
, maybe there's some standard way around the design
– abcalphabet
Nov 19 at 13:49
Yes, usestrtod
, which doesn't have this limitation. It behaves not as documented for subnormal numbers: it will return the subnormal value (so, contrary to the doc, it returns a non-zero value, yet sets errno=ERANGE). Which is good for us, because you can get the number you want.
– geza
Nov 19 at 13:53
1
1
Here, the difference lies in
std::stod
, doesn't it? GCC and clang throw out_of_range for subnormal numbers (which is weird, if you ask me), while msvc doesn't. I even don't understand, why they throw out_of_range for a small number which is truncated to zero. It's definitely not out_of_range. There should be a separate exception for this case.– geza
Nov 19 at 13:39
Here, the difference lies in
std::stod
, doesn't it? GCC and clang throw out_of_range for subnormal numbers (which is weird, if you ask me), while msvc doesn't. I even don't understand, why they throw out_of_range for a small number which is truncated to zero. It's definitely not out_of_range. There should be a separate exception for this case.– geza
Nov 19 at 13:39
Relevant: stackoverflow.com/questions/48086830/…
– geza
Nov 19 at 13:45
Relevant: stackoverflow.com/questions/48086830/…
– geza
Nov 19 at 13:45
1
1
std::stod
is badly designed. strtod
can report whether the ERANGE means overflow or underflow. std::stod
cannot.– geza
Nov 19 at 13:48
std::stod
is badly designed. strtod
can report whether the ERANGE means overflow or underflow. std::stod
cannot.– geza
Nov 19 at 13:48
@geza Thanks, edited the post to reflect that its
std::stod
, maybe there's some standard way around the design– abcalphabet
Nov 19 at 13:49
@geza Thanks, edited the post to reflect that its
std::stod
, maybe there's some standard way around the design– abcalphabet
Nov 19 at 13:49
Yes, use
strtod
, which doesn't have this limitation. It behaves not as documented for subnormal numbers: it will return the subnormal value (so, contrary to the doc, it returns a non-zero value, yet sets errno=ERANGE). Which is good for us, because you can get the number you want.– geza
Nov 19 at 13:53
Yes, use
strtod
, which doesn't have this limitation. It behaves not as documented for subnormal numbers: it will return the subnormal value (so, contrary to the doc, it returns a non-zero value, yet sets errno=ERANGE). Which is good for us, because you can get the number you want.– geza
Nov 19 at 13:53
|
show 1 more comment
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
Unfortunately, std::stod
is badly designed, because it is not possible to determine what caused the std::out_of_range
exception.
I'd suggest you to use strtod
instead. While is not specified in the standard what this function should do for subnormal numbers, it behaves well for subnormal numbers usually (it means that it returns subnormal numbers). The benefit of this function is that it returns a meaningful result for out-of-range situations, so it is possible to determine the cause of out-of-range.
If you want to handle out of range situations, you'll need to check errno
for ERANGE
. Note, that if a subnormal/zero number is a result, then maybe errno
will be set to ERANGE
, which you should ignore (you can check this out with fpclassify
).
So the logic is something like this:
double r = strtod(string, &end);
// here, check for end to know about invalid strings
if (errno==ERANGE) { // out-of-range (overflow, underflow)
int c = fpclassify(r);
if (c!=FP_SUBNORMAL&&c!=FP_ZERO) { // let's filter out underflow cases
// "real" out of range handling here, just overflow
}
}
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
Unfortunately, std::stod
is badly designed, because it is not possible to determine what caused the std::out_of_range
exception.
I'd suggest you to use strtod
instead. While is not specified in the standard what this function should do for subnormal numbers, it behaves well for subnormal numbers usually (it means that it returns subnormal numbers). The benefit of this function is that it returns a meaningful result for out-of-range situations, so it is possible to determine the cause of out-of-range.
If you want to handle out of range situations, you'll need to check errno
for ERANGE
. Note, that if a subnormal/zero number is a result, then maybe errno
will be set to ERANGE
, which you should ignore (you can check this out with fpclassify
).
So the logic is something like this:
double r = strtod(string, &end);
// here, check for end to know about invalid strings
if (errno==ERANGE) { // out-of-range (overflow, underflow)
int c = fpclassify(r);
if (c!=FP_SUBNORMAL&&c!=FP_ZERO) { // let's filter out underflow cases
// "real" out of range handling here, just overflow
}
}
add a comment |
up vote
3
down vote
accepted
Unfortunately, std::stod
is badly designed, because it is not possible to determine what caused the std::out_of_range
exception.
I'd suggest you to use strtod
instead. While is not specified in the standard what this function should do for subnormal numbers, it behaves well for subnormal numbers usually (it means that it returns subnormal numbers). The benefit of this function is that it returns a meaningful result for out-of-range situations, so it is possible to determine the cause of out-of-range.
If you want to handle out of range situations, you'll need to check errno
for ERANGE
. Note, that if a subnormal/zero number is a result, then maybe errno
will be set to ERANGE
, which you should ignore (you can check this out with fpclassify
).
So the logic is something like this:
double r = strtod(string, &end);
// here, check for end to know about invalid strings
if (errno==ERANGE) { // out-of-range (overflow, underflow)
int c = fpclassify(r);
if (c!=FP_SUBNORMAL&&c!=FP_ZERO) { // let's filter out underflow cases
// "real" out of range handling here, just overflow
}
}
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
Unfortunately, std::stod
is badly designed, because it is not possible to determine what caused the std::out_of_range
exception.
I'd suggest you to use strtod
instead. While is not specified in the standard what this function should do for subnormal numbers, it behaves well for subnormal numbers usually (it means that it returns subnormal numbers). The benefit of this function is that it returns a meaningful result for out-of-range situations, so it is possible to determine the cause of out-of-range.
If you want to handle out of range situations, you'll need to check errno
for ERANGE
. Note, that if a subnormal/zero number is a result, then maybe errno
will be set to ERANGE
, which you should ignore (you can check this out with fpclassify
).
So the logic is something like this:
double r = strtod(string, &end);
// here, check for end to know about invalid strings
if (errno==ERANGE) { // out-of-range (overflow, underflow)
int c = fpclassify(r);
if (c!=FP_SUBNORMAL&&c!=FP_ZERO) { // let's filter out underflow cases
// "real" out of range handling here, just overflow
}
}
Unfortunately, std::stod
is badly designed, because it is not possible to determine what caused the std::out_of_range
exception.
I'd suggest you to use strtod
instead. While is not specified in the standard what this function should do for subnormal numbers, it behaves well for subnormal numbers usually (it means that it returns subnormal numbers). The benefit of this function is that it returns a meaningful result for out-of-range situations, so it is possible to determine the cause of out-of-range.
If you want to handle out of range situations, you'll need to check errno
for ERANGE
. Note, that if a subnormal/zero number is a result, then maybe errno
will be set to ERANGE
, which you should ignore (you can check this out with fpclassify
).
So the logic is something like this:
double r = strtod(string, &end);
// here, check for end to know about invalid strings
if (errno==ERANGE) { // out-of-range (overflow, underflow)
int c = fpclassify(r);
if (c!=FP_SUBNORMAL&&c!=FP_ZERO) { // let's filter out underflow cases
// "real" out of range handling here, just overflow
}
}
answered Nov 19 at 18:01
geza
12.3k32774
12.3k32774
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53375554%2fexplicit-specification-of-the-double-precision-representation-used-by-compiler%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Here, the difference lies in
std::stod
, doesn't it? GCC and clang throw out_of_range for subnormal numbers (which is weird, if you ask me), while msvc doesn't. I even don't understand, why they throw out_of_range for a small number which is truncated to zero. It's definitely not out_of_range. There should be a separate exception for this case.– geza
Nov 19 at 13:39
Relevant: stackoverflow.com/questions/48086830/…
– geza
Nov 19 at 13:45
1
std::stod
is badly designed.strtod
can report whether the ERANGE means overflow or underflow.std::stod
cannot.– geza
Nov 19 at 13:48
@geza Thanks, edited the post to reflect that its
std::stod
, maybe there's some standard way around the design– abcalphabet
Nov 19 at 13:49
Yes, use
strtod
, which doesn't have this limitation. It behaves not as documented for subnormal numbers: it will return the subnormal value (so, contrary to the doc, it returns a non-zero value, yet sets errno=ERANGE). Which is good for us, because you can get the number you want.– geza
Nov 19 at 13:53