Is binary equality comparison of floats correct?
Clash Royale CLAN TAG#URR8PPP
I'm working on different memory block manipulation functions and during benchmarks I noticed, that my implementation of the IsEqualRange(double* begin1, double* end1, double* begin2, double* end2)
is much faster then the std::equals(...)
on MSVC and GCC as well. Further investigation showed, that doubles and floats are not block compared by memcmp
, but in a for loop one by one.
In what situation does binary comparison of floats lead to incorrect result? When is it ok to binary compare (equality) array of floats/doubles? Are there other fundamental types where I shouldn't use memcmp
?
c++ floating-point std
|
show 1 more comment
I'm working on different memory block manipulation functions and during benchmarks I noticed, that my implementation of the IsEqualRange(double* begin1, double* end1, double* begin2, double* end2)
is much faster then the std::equals(...)
on MSVC and GCC as well. Further investigation showed, that doubles and floats are not block compared by memcmp
, but in a for loop one by one.
In what situation does binary comparison of floats lead to incorrect result? When is it ok to binary compare (equality) array of floats/doubles? Are there other fundamental types where I shouldn't use memcmp
?
c++ floating-point std
1
Related: stackoverflow.com/questions/25808445/…
– DeiDei
Jan 3 at 10:49
1
This answer to a related question is relevant to yours
– Basile Starynkevitch
Jan 3 at 10:52
3
@BasileStarynkevitch That is related to the nature of the floating points where not every number can be represented. Doesn't say much about the equality in binary form.
– Zoltan Tirinda
Jan 3 at 10:57
2
Similar: stackoverflow.com/q/8044862/560648
– Lightness Races in Orbit
Jan 3 at 11:25
@ZoltanTirinda But this affect equality because any non trivial calculation will encounter this not representable numbers during processing and this will affect final result. Every time someone use==
then is good to mention this that it will not always do what you want (because of previous operations). You can know this but for other do not.
– Yankes
Jan 3 at 12:15
|
show 1 more comment
I'm working on different memory block manipulation functions and during benchmarks I noticed, that my implementation of the IsEqualRange(double* begin1, double* end1, double* begin2, double* end2)
is much faster then the std::equals(...)
on MSVC and GCC as well. Further investigation showed, that doubles and floats are not block compared by memcmp
, but in a for loop one by one.
In what situation does binary comparison of floats lead to incorrect result? When is it ok to binary compare (equality) array of floats/doubles? Are there other fundamental types where I shouldn't use memcmp
?
c++ floating-point std
I'm working on different memory block manipulation functions and during benchmarks I noticed, that my implementation of the IsEqualRange(double* begin1, double* end1, double* begin2, double* end2)
is much faster then the std::equals(...)
on MSVC and GCC as well. Further investigation showed, that doubles and floats are not block compared by memcmp
, but in a for loop one by one.
In what situation does binary comparison of floats lead to incorrect result? When is it ok to binary compare (equality) array of floats/doubles? Are there other fundamental types where I shouldn't use memcmp
?
c++ floating-point std
c++ floating-point std
asked Jan 3 at 10:46
Zoltan TirindaZoltan Tirinda
469721
469721
1
Related: stackoverflow.com/questions/25808445/…
– DeiDei
Jan 3 at 10:49
1
This answer to a related question is relevant to yours
– Basile Starynkevitch
Jan 3 at 10:52
3
@BasileStarynkevitch That is related to the nature of the floating points where not every number can be represented. Doesn't say much about the equality in binary form.
– Zoltan Tirinda
Jan 3 at 10:57
2
Similar: stackoverflow.com/q/8044862/560648
– Lightness Races in Orbit
Jan 3 at 11:25
@ZoltanTirinda But this affect equality because any non trivial calculation will encounter this not representable numbers during processing and this will affect final result. Every time someone use==
then is good to mention this that it will not always do what you want (because of previous operations). You can know this but for other do not.
– Yankes
Jan 3 at 12:15
|
show 1 more comment
1
Related: stackoverflow.com/questions/25808445/…
– DeiDei
Jan 3 at 10:49
1
This answer to a related question is relevant to yours
– Basile Starynkevitch
Jan 3 at 10:52
3
@BasileStarynkevitch That is related to the nature of the floating points where not every number can be represented. Doesn't say much about the equality in binary form.
– Zoltan Tirinda
Jan 3 at 10:57
2
Similar: stackoverflow.com/q/8044862/560648
– Lightness Races in Orbit
Jan 3 at 11:25
@ZoltanTirinda But this affect equality because any non trivial calculation will encounter this not representable numbers during processing and this will affect final result. Every time someone use==
then is good to mention this that it will not always do what you want (because of previous operations). You can know this but for other do not.
– Yankes
Jan 3 at 12:15
1
1
Related: stackoverflow.com/questions/25808445/…
– DeiDei
Jan 3 at 10:49
Related: stackoverflow.com/questions/25808445/…
– DeiDei
Jan 3 at 10:49
1
1
This answer to a related question is relevant to yours
– Basile Starynkevitch
Jan 3 at 10:52
This answer to a related question is relevant to yours
– Basile Starynkevitch
Jan 3 at 10:52
3
3
@BasileStarynkevitch That is related to the nature of the floating points where not every number can be represented. Doesn't say much about the equality in binary form.
– Zoltan Tirinda
Jan 3 at 10:57
@BasileStarynkevitch That is related to the nature of the floating points where not every number can be represented. Doesn't say much about the equality in binary form.
– Zoltan Tirinda
Jan 3 at 10:57
2
2
Similar: stackoverflow.com/q/8044862/560648
– Lightness Races in Orbit
Jan 3 at 11:25
Similar: stackoverflow.com/q/8044862/560648
– Lightness Races in Orbit
Jan 3 at 11:25
@ZoltanTirinda But this affect equality because any non trivial calculation will encounter this not representable numbers during processing and this will affect final result. Every time someone use
==
then is good to mention this that it will not always do what you want (because of previous operations). You can know this but for other do not.– Yankes
Jan 3 at 12:15
@ZoltanTirinda But this affect equality because any non trivial calculation will encounter this not representable numbers during processing and this will affect final result. Every time someone use
==
then is good to mention this that it will not always do what you want (because of previous operations). You can know this but for other do not.– Yankes
Jan 3 at 12:15
|
show 1 more comment
3 Answers
3
active
oldest
votes
The first thing I would do if I were you is to check your optimisation settings.
It's fine to use memcmp
for an array of floating points but note that you could get different results to element-by-element ==
. In particular, for IEEE754 floating point:
+0.0 is defined to compare equal to -0.0.
NaN is defined to compare not-equal to NaN.
3
Also note that, technically, the C and C++ standards do not require the use of IEEE 754 to implementfloat
anddouble
. Most "reasonable" (modern) platforms will do so in practice, of course. But if you're uncertain that IEEE 754 is in use, then you have very few guarantees of how the==
operator will behave on arbitrary bit patterns. A "weird" architecture could for example decide that((float)0x00000000) == ((float)0x12345678)
, butmemcmp
will obviously consider those bytes different.
– Kevin
Jan 4 at 1:25
@Kevin: Indeed you're correct and I've narrowed the answer. I wonder if you fancy answering this question in more detail yourself; it seems to have attracted a lot of attention?
– Bathsheba
Jan 4 at 8:18
Thanks for the vote of confidence, but I don't really think I can add much to your answer as it now stands.
– Kevin
Jan 4 at 14:18
add a comment |
The main issue is nan
values, as these are never equal to themselves. There is also two representations of 0 (+0
and -0
) that are equal but not binary equal.
So strictly speaking, you cannot use memcmp
for them, as the answer would be mathematically incorrect.
If you know that you don't have nan
or 0
values, then you can use memcmp
.
5
Zero has two representations in IEEE-754 binary floating-point, denoted as −0 and +0. They represent the same mathematical value and should be reported as equal, which==
does butmemcmp
does not.
– Eric Postpischil
Jan 3 at 13:10
1
Yes indeed, that's why I said the main issue, of course, there is 0 as well.
– Matthieu Brucher
Jan 3 at 13:30
1
There's another way to get two numbers that compare numerically equal but not binary equal: if a denormalized float somehow leaks into your system. That's not supposed to happen (IEEE-754 specifies which representation should be used if a number can be represented in more than one way), but it's something to keep in mind if you're operating on, say, data files provided by a hostile user.
– Mark
Jan 4 at 0:39
add a comment |
Binary compare works with too much precision for many actual applications. For example, in javascript, 0.2 / 10.0 != 0.1 * 0.2 If you have two variables that both end up with very, very slight rounding errors, they will be unequal despite representing the "same" number.
5
Yes, but in that case both==
andmemcmp(…)
(and, presumably,std::equals(…)
) would agree, so that's not addressing the question. (Worth being aware of, though.)
– gidds
Jan 3 at 17:44
1
They are not the "same" number if their binary representation is different. If you want both numbers to be the same with two decimal precision then you round them. Then you define how you want to round them. You document that and have a reliable way of testing logic. What do you call the same number? Is this good enough for you 0.099998 == 0.99997? Is this good enough 0.099 == 0.098? Is this good enough 0.9 == 1.0?
– FCin
Jan 3 at 18:34
@FCin So, are you saying that 0.2*0.1 != 0.2/10.0? They aren't the same number because of rounding errors, not because the numbers they should represent are different. If your code only uses hardcoded numbers, then it's fine, but if any of the numbers are random or user-generated, then using == is a bad decision for floating point numbers and likely to introduce bugs.
– David Rice
Jan 3 at 18:42
1
As @gidds said, that's completely irrelevant to the question. The only time==
differs frommemcmp(...)
occurs withNaN
and +0 and -0. Also, there is a difference you're missing here: C floating point isn't mathematically perfect. If you put in0.2 / 10.0
and0.1 * 0.2
and expect them to evaluate to the same value, you need to read more about floating point.
– user124
Jan 3 at 20:16
1
@DavidRice is correct. A more complete answer referencing epsilon can be found here.
– jacknad
Jan 3 at 21:14
|
show 6 more comments
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
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%2f54020760%2fis-binary-equality-comparison-of-floats-correct%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
The first thing I would do if I were you is to check your optimisation settings.
It's fine to use memcmp
for an array of floating points but note that you could get different results to element-by-element ==
. In particular, for IEEE754 floating point:
+0.0 is defined to compare equal to -0.0.
NaN is defined to compare not-equal to NaN.
3
Also note that, technically, the C and C++ standards do not require the use of IEEE 754 to implementfloat
anddouble
. Most "reasonable" (modern) platforms will do so in practice, of course. But if you're uncertain that IEEE 754 is in use, then you have very few guarantees of how the==
operator will behave on arbitrary bit patterns. A "weird" architecture could for example decide that((float)0x00000000) == ((float)0x12345678)
, butmemcmp
will obviously consider those bytes different.
– Kevin
Jan 4 at 1:25
@Kevin: Indeed you're correct and I've narrowed the answer. I wonder if you fancy answering this question in more detail yourself; it seems to have attracted a lot of attention?
– Bathsheba
Jan 4 at 8:18
Thanks for the vote of confidence, but I don't really think I can add much to your answer as it now stands.
– Kevin
Jan 4 at 14:18
add a comment |
The first thing I would do if I were you is to check your optimisation settings.
It's fine to use memcmp
for an array of floating points but note that you could get different results to element-by-element ==
. In particular, for IEEE754 floating point:
+0.0 is defined to compare equal to -0.0.
NaN is defined to compare not-equal to NaN.
3
Also note that, technically, the C and C++ standards do not require the use of IEEE 754 to implementfloat
anddouble
. Most "reasonable" (modern) platforms will do so in practice, of course. But if you're uncertain that IEEE 754 is in use, then you have very few guarantees of how the==
operator will behave on arbitrary bit patterns. A "weird" architecture could for example decide that((float)0x00000000) == ((float)0x12345678)
, butmemcmp
will obviously consider those bytes different.
– Kevin
Jan 4 at 1:25
@Kevin: Indeed you're correct and I've narrowed the answer. I wonder if you fancy answering this question in more detail yourself; it seems to have attracted a lot of attention?
– Bathsheba
Jan 4 at 8:18
Thanks for the vote of confidence, but I don't really think I can add much to your answer as it now stands.
– Kevin
Jan 4 at 14:18
add a comment |
The first thing I would do if I were you is to check your optimisation settings.
It's fine to use memcmp
for an array of floating points but note that you could get different results to element-by-element ==
. In particular, for IEEE754 floating point:
+0.0 is defined to compare equal to -0.0.
NaN is defined to compare not-equal to NaN.
The first thing I would do if I were you is to check your optimisation settings.
It's fine to use memcmp
for an array of floating points but note that you could get different results to element-by-element ==
. In particular, for IEEE754 floating point:
+0.0 is defined to compare equal to -0.0.
NaN is defined to compare not-equal to NaN.
edited Jan 4 at 8:12
answered Jan 3 at 10:48
BathshebaBathsheba
176k27251373
176k27251373
3
Also note that, technically, the C and C++ standards do not require the use of IEEE 754 to implementfloat
anddouble
. Most "reasonable" (modern) platforms will do so in practice, of course. But if you're uncertain that IEEE 754 is in use, then you have very few guarantees of how the==
operator will behave on arbitrary bit patterns. A "weird" architecture could for example decide that((float)0x00000000) == ((float)0x12345678)
, butmemcmp
will obviously consider those bytes different.
– Kevin
Jan 4 at 1:25
@Kevin: Indeed you're correct and I've narrowed the answer. I wonder if you fancy answering this question in more detail yourself; it seems to have attracted a lot of attention?
– Bathsheba
Jan 4 at 8:18
Thanks for the vote of confidence, but I don't really think I can add much to your answer as it now stands.
– Kevin
Jan 4 at 14:18
add a comment |
3
Also note that, technically, the C and C++ standards do not require the use of IEEE 754 to implementfloat
anddouble
. Most "reasonable" (modern) platforms will do so in practice, of course. But if you're uncertain that IEEE 754 is in use, then you have very few guarantees of how the==
operator will behave on arbitrary bit patterns. A "weird" architecture could for example decide that((float)0x00000000) == ((float)0x12345678)
, butmemcmp
will obviously consider those bytes different.
– Kevin
Jan 4 at 1:25
@Kevin: Indeed you're correct and I've narrowed the answer. I wonder if you fancy answering this question in more detail yourself; it seems to have attracted a lot of attention?
– Bathsheba
Jan 4 at 8:18
Thanks for the vote of confidence, but I don't really think I can add much to your answer as it now stands.
– Kevin
Jan 4 at 14:18
3
3
Also note that, technically, the C and C++ standards do not require the use of IEEE 754 to implement
float
and double
. Most "reasonable" (modern) platforms will do so in practice, of course. But if you're uncertain that IEEE 754 is in use, then you have very few guarantees of how the ==
operator will behave on arbitrary bit patterns. A "weird" architecture could for example decide that ((float)0x00000000) == ((float)0x12345678)
, but memcmp
will obviously consider those bytes different.– Kevin
Jan 4 at 1:25
Also note that, technically, the C and C++ standards do not require the use of IEEE 754 to implement
float
and double
. Most "reasonable" (modern) platforms will do so in practice, of course. But if you're uncertain that IEEE 754 is in use, then you have very few guarantees of how the ==
operator will behave on arbitrary bit patterns. A "weird" architecture could for example decide that ((float)0x00000000) == ((float)0x12345678)
, but memcmp
will obviously consider those bytes different.– Kevin
Jan 4 at 1:25
@Kevin: Indeed you're correct and I've narrowed the answer. I wonder if you fancy answering this question in more detail yourself; it seems to have attracted a lot of attention?
– Bathsheba
Jan 4 at 8:18
@Kevin: Indeed you're correct and I've narrowed the answer. I wonder if you fancy answering this question in more detail yourself; it seems to have attracted a lot of attention?
– Bathsheba
Jan 4 at 8:18
Thanks for the vote of confidence, but I don't really think I can add much to your answer as it now stands.
– Kevin
Jan 4 at 14:18
Thanks for the vote of confidence, but I don't really think I can add much to your answer as it now stands.
– Kevin
Jan 4 at 14:18
add a comment |
The main issue is nan
values, as these are never equal to themselves. There is also two representations of 0 (+0
and -0
) that are equal but not binary equal.
So strictly speaking, you cannot use memcmp
for them, as the answer would be mathematically incorrect.
If you know that you don't have nan
or 0
values, then you can use memcmp
.
5
Zero has two representations in IEEE-754 binary floating-point, denoted as −0 and +0. They represent the same mathematical value and should be reported as equal, which==
does butmemcmp
does not.
– Eric Postpischil
Jan 3 at 13:10
1
Yes indeed, that's why I said the main issue, of course, there is 0 as well.
– Matthieu Brucher
Jan 3 at 13:30
1
There's another way to get two numbers that compare numerically equal but not binary equal: if a denormalized float somehow leaks into your system. That's not supposed to happen (IEEE-754 specifies which representation should be used if a number can be represented in more than one way), but it's something to keep in mind if you're operating on, say, data files provided by a hostile user.
– Mark
Jan 4 at 0:39
add a comment |
The main issue is nan
values, as these are never equal to themselves. There is also two representations of 0 (+0
and -0
) that are equal but not binary equal.
So strictly speaking, you cannot use memcmp
for them, as the answer would be mathematically incorrect.
If you know that you don't have nan
or 0
values, then you can use memcmp
.
5
Zero has two representations in IEEE-754 binary floating-point, denoted as −0 and +0. They represent the same mathematical value and should be reported as equal, which==
does butmemcmp
does not.
– Eric Postpischil
Jan 3 at 13:10
1
Yes indeed, that's why I said the main issue, of course, there is 0 as well.
– Matthieu Brucher
Jan 3 at 13:30
1
There's another way to get two numbers that compare numerically equal but not binary equal: if a denormalized float somehow leaks into your system. That's not supposed to happen (IEEE-754 specifies which representation should be used if a number can be represented in more than one way), but it's something to keep in mind if you're operating on, say, data files provided by a hostile user.
– Mark
Jan 4 at 0:39
add a comment |
The main issue is nan
values, as these are never equal to themselves. There is also two representations of 0 (+0
and -0
) that are equal but not binary equal.
So strictly speaking, you cannot use memcmp
for them, as the answer would be mathematically incorrect.
If you know that you don't have nan
or 0
values, then you can use memcmp
.
The main issue is nan
values, as these are never equal to themselves. There is also two representations of 0 (+0
and -0
) that are equal but not binary equal.
So strictly speaking, you cannot use memcmp
for them, as the answer would be mathematically incorrect.
If you know that you don't have nan
or 0
values, then you can use memcmp
.
edited Jan 3 at 13:50
answered Jan 3 at 10:48
Matthieu BrucherMatthieu Brucher
13.7k32140
13.7k32140
5
Zero has two representations in IEEE-754 binary floating-point, denoted as −0 and +0. They represent the same mathematical value and should be reported as equal, which==
does butmemcmp
does not.
– Eric Postpischil
Jan 3 at 13:10
1
Yes indeed, that's why I said the main issue, of course, there is 0 as well.
– Matthieu Brucher
Jan 3 at 13:30
1
There's another way to get two numbers that compare numerically equal but not binary equal: if a denormalized float somehow leaks into your system. That's not supposed to happen (IEEE-754 specifies which representation should be used if a number can be represented in more than one way), but it's something to keep in mind if you're operating on, say, data files provided by a hostile user.
– Mark
Jan 4 at 0:39
add a comment |
5
Zero has two representations in IEEE-754 binary floating-point, denoted as −0 and +0. They represent the same mathematical value and should be reported as equal, which==
does butmemcmp
does not.
– Eric Postpischil
Jan 3 at 13:10
1
Yes indeed, that's why I said the main issue, of course, there is 0 as well.
– Matthieu Brucher
Jan 3 at 13:30
1
There's another way to get two numbers that compare numerically equal but not binary equal: if a denormalized float somehow leaks into your system. That's not supposed to happen (IEEE-754 specifies which representation should be used if a number can be represented in more than one way), but it's something to keep in mind if you're operating on, say, data files provided by a hostile user.
– Mark
Jan 4 at 0:39
5
5
Zero has two representations in IEEE-754 binary floating-point, denoted as −0 and +0. They represent the same mathematical value and should be reported as equal, which
==
does but memcmp
does not.– Eric Postpischil
Jan 3 at 13:10
Zero has two representations in IEEE-754 binary floating-point, denoted as −0 and +0. They represent the same mathematical value and should be reported as equal, which
==
does but memcmp
does not.– Eric Postpischil
Jan 3 at 13:10
1
1
Yes indeed, that's why I said the main issue, of course, there is 0 as well.
– Matthieu Brucher
Jan 3 at 13:30
Yes indeed, that's why I said the main issue, of course, there is 0 as well.
– Matthieu Brucher
Jan 3 at 13:30
1
1
There's another way to get two numbers that compare numerically equal but not binary equal: if a denormalized float somehow leaks into your system. That's not supposed to happen (IEEE-754 specifies which representation should be used if a number can be represented in more than one way), but it's something to keep in mind if you're operating on, say, data files provided by a hostile user.
– Mark
Jan 4 at 0:39
There's another way to get two numbers that compare numerically equal but not binary equal: if a denormalized float somehow leaks into your system. That's not supposed to happen (IEEE-754 specifies which representation should be used if a number can be represented in more than one way), but it's something to keep in mind if you're operating on, say, data files provided by a hostile user.
– Mark
Jan 4 at 0:39
add a comment |
Binary compare works with too much precision for many actual applications. For example, in javascript, 0.2 / 10.0 != 0.1 * 0.2 If you have two variables that both end up with very, very slight rounding errors, they will be unequal despite representing the "same" number.
5
Yes, but in that case both==
andmemcmp(…)
(and, presumably,std::equals(…)
) would agree, so that's not addressing the question. (Worth being aware of, though.)
– gidds
Jan 3 at 17:44
1
They are not the "same" number if their binary representation is different. If you want both numbers to be the same with two decimal precision then you round them. Then you define how you want to round them. You document that and have a reliable way of testing logic. What do you call the same number? Is this good enough for you 0.099998 == 0.99997? Is this good enough 0.099 == 0.098? Is this good enough 0.9 == 1.0?
– FCin
Jan 3 at 18:34
@FCin So, are you saying that 0.2*0.1 != 0.2/10.0? They aren't the same number because of rounding errors, not because the numbers they should represent are different. If your code only uses hardcoded numbers, then it's fine, but if any of the numbers are random or user-generated, then using == is a bad decision for floating point numbers and likely to introduce bugs.
– David Rice
Jan 3 at 18:42
1
As @gidds said, that's completely irrelevant to the question. The only time==
differs frommemcmp(...)
occurs withNaN
and +0 and -0. Also, there is a difference you're missing here: C floating point isn't mathematically perfect. If you put in0.2 / 10.0
and0.1 * 0.2
and expect them to evaluate to the same value, you need to read more about floating point.
– user124
Jan 3 at 20:16
1
@DavidRice is correct. A more complete answer referencing epsilon can be found here.
– jacknad
Jan 3 at 21:14
|
show 6 more comments
Binary compare works with too much precision for many actual applications. For example, in javascript, 0.2 / 10.0 != 0.1 * 0.2 If you have two variables that both end up with very, very slight rounding errors, they will be unequal despite representing the "same" number.
5
Yes, but in that case both==
andmemcmp(…)
(and, presumably,std::equals(…)
) would agree, so that's not addressing the question. (Worth being aware of, though.)
– gidds
Jan 3 at 17:44
1
They are not the "same" number if their binary representation is different. If you want both numbers to be the same with two decimal precision then you round them. Then you define how you want to round them. You document that and have a reliable way of testing logic. What do you call the same number? Is this good enough for you 0.099998 == 0.99997? Is this good enough 0.099 == 0.098? Is this good enough 0.9 == 1.0?
– FCin
Jan 3 at 18:34
@FCin So, are you saying that 0.2*0.1 != 0.2/10.0? They aren't the same number because of rounding errors, not because the numbers they should represent are different. If your code only uses hardcoded numbers, then it's fine, but if any of the numbers are random or user-generated, then using == is a bad decision for floating point numbers and likely to introduce bugs.
– David Rice
Jan 3 at 18:42
1
As @gidds said, that's completely irrelevant to the question. The only time==
differs frommemcmp(...)
occurs withNaN
and +0 and -0. Also, there is a difference you're missing here: C floating point isn't mathematically perfect. If you put in0.2 / 10.0
and0.1 * 0.2
and expect them to evaluate to the same value, you need to read more about floating point.
– user124
Jan 3 at 20:16
1
@DavidRice is correct. A more complete answer referencing epsilon can be found here.
– jacknad
Jan 3 at 21:14
|
show 6 more comments
Binary compare works with too much precision for many actual applications. For example, in javascript, 0.2 / 10.0 != 0.1 * 0.2 If you have two variables that both end up with very, very slight rounding errors, they will be unequal despite representing the "same" number.
Binary compare works with too much precision for many actual applications. For example, in javascript, 0.2 / 10.0 != 0.1 * 0.2 If you have two variables that both end up with very, very slight rounding errors, they will be unequal despite representing the "same" number.
answered Jan 3 at 16:50
David RiceDavid Rice
1282
1282
5
Yes, but in that case both==
andmemcmp(…)
(and, presumably,std::equals(…)
) would agree, so that's not addressing the question. (Worth being aware of, though.)
– gidds
Jan 3 at 17:44
1
They are not the "same" number if their binary representation is different. If you want both numbers to be the same with two decimal precision then you round them. Then you define how you want to round them. You document that and have a reliable way of testing logic. What do you call the same number? Is this good enough for you 0.099998 == 0.99997? Is this good enough 0.099 == 0.098? Is this good enough 0.9 == 1.0?
– FCin
Jan 3 at 18:34
@FCin So, are you saying that 0.2*0.1 != 0.2/10.0? They aren't the same number because of rounding errors, not because the numbers they should represent are different. If your code only uses hardcoded numbers, then it's fine, but if any of the numbers are random or user-generated, then using == is a bad decision for floating point numbers and likely to introduce bugs.
– David Rice
Jan 3 at 18:42
1
As @gidds said, that's completely irrelevant to the question. The only time==
differs frommemcmp(...)
occurs withNaN
and +0 and -0. Also, there is a difference you're missing here: C floating point isn't mathematically perfect. If you put in0.2 / 10.0
and0.1 * 0.2
and expect them to evaluate to the same value, you need to read more about floating point.
– user124
Jan 3 at 20:16
1
@DavidRice is correct. A more complete answer referencing epsilon can be found here.
– jacknad
Jan 3 at 21:14
|
show 6 more comments
5
Yes, but in that case both==
andmemcmp(…)
(and, presumably,std::equals(…)
) would agree, so that's not addressing the question. (Worth being aware of, though.)
– gidds
Jan 3 at 17:44
1
They are not the "same" number if their binary representation is different. If you want both numbers to be the same with two decimal precision then you round them. Then you define how you want to round them. You document that and have a reliable way of testing logic. What do you call the same number? Is this good enough for you 0.099998 == 0.99997? Is this good enough 0.099 == 0.098? Is this good enough 0.9 == 1.0?
– FCin
Jan 3 at 18:34
@FCin So, are you saying that 0.2*0.1 != 0.2/10.0? They aren't the same number because of rounding errors, not because the numbers they should represent are different. If your code only uses hardcoded numbers, then it's fine, but if any of the numbers are random or user-generated, then using == is a bad decision for floating point numbers and likely to introduce bugs.
– David Rice
Jan 3 at 18:42
1
As @gidds said, that's completely irrelevant to the question. The only time==
differs frommemcmp(...)
occurs withNaN
and +0 and -0. Also, there is a difference you're missing here: C floating point isn't mathematically perfect. If you put in0.2 / 10.0
and0.1 * 0.2
and expect them to evaluate to the same value, you need to read more about floating point.
– user124
Jan 3 at 20:16
1
@DavidRice is correct. A more complete answer referencing epsilon can be found here.
– jacknad
Jan 3 at 21:14
5
5
Yes, but in that case both
==
and memcmp(…)
(and, presumably, std::equals(…)
) would agree, so that's not addressing the question. (Worth being aware of, though.)– gidds
Jan 3 at 17:44
Yes, but in that case both
==
and memcmp(…)
(and, presumably, std::equals(…)
) would agree, so that's not addressing the question. (Worth being aware of, though.)– gidds
Jan 3 at 17:44
1
1
They are not the "same" number if their binary representation is different. If you want both numbers to be the same with two decimal precision then you round them. Then you define how you want to round them. You document that and have a reliable way of testing logic. What do you call the same number? Is this good enough for you 0.099998 == 0.99997? Is this good enough 0.099 == 0.098? Is this good enough 0.9 == 1.0?
– FCin
Jan 3 at 18:34
They are not the "same" number if their binary representation is different. If you want both numbers to be the same with two decimal precision then you round them. Then you define how you want to round them. You document that and have a reliable way of testing logic. What do you call the same number? Is this good enough for you 0.099998 == 0.99997? Is this good enough 0.099 == 0.098? Is this good enough 0.9 == 1.0?
– FCin
Jan 3 at 18:34
@FCin So, are you saying that 0.2*0.1 != 0.2/10.0? They aren't the same number because of rounding errors, not because the numbers they should represent are different. If your code only uses hardcoded numbers, then it's fine, but if any of the numbers are random or user-generated, then using == is a bad decision for floating point numbers and likely to introduce bugs.
– David Rice
Jan 3 at 18:42
@FCin So, are you saying that 0.2*0.1 != 0.2/10.0? They aren't the same number because of rounding errors, not because the numbers they should represent are different. If your code only uses hardcoded numbers, then it's fine, but if any of the numbers are random or user-generated, then using == is a bad decision for floating point numbers and likely to introduce bugs.
– David Rice
Jan 3 at 18:42
1
1
As @gidds said, that's completely irrelevant to the question. The only time
==
differs from memcmp(...)
occurs with NaN
and +0 and -0. Also, there is a difference you're missing here: C floating point isn't mathematically perfect. If you put in 0.2 / 10.0
and 0.1 * 0.2
and expect them to evaluate to the same value, you need to read more about floating point.– user124
Jan 3 at 20:16
As @gidds said, that's completely irrelevant to the question. The only time
==
differs from memcmp(...)
occurs with NaN
and +0 and -0. Also, there is a difference you're missing here: C floating point isn't mathematically perfect. If you put in 0.2 / 10.0
and 0.1 * 0.2
and expect them to evaluate to the same value, you need to read more about floating point.– user124
Jan 3 at 20:16
1
1
@DavidRice is correct. A more complete answer referencing epsilon can be found here.
– jacknad
Jan 3 at 21:14
@DavidRice is correct. A more complete answer referencing epsilon can be found here.
– jacknad
Jan 3 at 21:14
|
show 6 more comments
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.
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%2f54020760%2fis-binary-equality-comparison-of-floats-correct%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
Related: stackoverflow.com/questions/25808445/…
– DeiDei
Jan 3 at 10:49
1
This answer to a related question is relevant to yours
– Basile Starynkevitch
Jan 3 at 10:52
3
@BasileStarynkevitch That is related to the nature of the floating points where not every number can be represented. Doesn't say much about the equality in binary form.
– Zoltan Tirinda
Jan 3 at 10:57
2
Similar: stackoverflow.com/q/8044862/560648
– Lightness Races in Orbit
Jan 3 at 11:25
@ZoltanTirinda But this affect equality because any non trivial calculation will encounter this not representable numbers during processing and this will affect final result. Every time someone use
==
then is good to mention this that it will not always do what you want (because of previous operations). You can know this but for other do not.– Yankes
Jan 3 at 12:15