https://erlangforums.com/t/in-erlang-otp-27-0-0-will-no-longer-be-exactly-equal-to-0-0/2586 Erlang Forums In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0 Erlang News & Announcements Erlang Notices float, incompatible bjorng May 5, 2023, 8:20am 1 Currently, the floating point numbers 0.0 and -0.0 have distinct internal representations. That can be seen if they are converted to binaries: 1> <<0.0/float>>. <<0,0,0,0,0,0,0,0>> 2> <<-0.0/float>>. <<128,0,0,0,0,0,0,0>> However, when they are matched against each other or compared using the =:= operator, they are considered to be equal. Thus, 0.0 =:= -0.0 currently returns true. @nzok considers this behaviour to be a bug. We also consider it a bug, but until recently we were not sure that fixing and introducing an incompatibility would be be worth it. A recent bug found by erlfuzz made us reconsider. An optimization in the compiler to share identical code would consider the code for the two clauses in this function to be identical: f(_V0, _V0) -> -0.0; f(_, _) -> 0.0. and essentially rewrite it to: f(_, _) -> 0.0. To fix this optimization when =:= considers 0.0 and -0.0 to be equal would be cumbersome and could make the compiler slower. It also likely that other optimizations in the compiler could be affected and would have to be fixed in similarly cumbersome ways. Therefore, the OTP Technical Board decided that in Erlang/OTP 27, we will change +0.0 =:= -0.0 so that it will return false, and matching positive and negative 0.0 against each other will also fail. When used as map keys, 0.0 and -0.0 will be considered to be distinct. The == operator will continue to return true for 0.0 == -0.0. To help to find code that might need to be revised, in OTP 27 there will be a new compiler warning when matching against 0.0 or comparing to that value using the =:= operator. The warning can be suppressed by matching against +0.0 instead of 0.0. We also plan to introduce the same warning in OTP 26.1, but by default it will be disabled. Anyone that suspect they have code that might be affected can turn on that warning in OTP 26.1. 23 Likes bjorng Pinned May 5, 2023, 8:26am 2 eiji7 May 6, 2023, 12:54pm 3 Interesting ... for people not in topic could you also please describe (or link to some article) why <<-0.0/float>> is represented as <<128,0,0,0,0,0,0,0>>? I think that many people and especially newbies would be confused and assume that -0.0 and +0.0 is always seen the same i.e. 0.0. If I understand correctly regardless of value (0.0, 12.34, -98.76, ...) first bit of every float is 0 (positive) or 128 (negative) and Erlang previously saw that like: defmodule Example do def negative?(<<128, _data::8*7>>), do: true def negative?(<<_sign, _data::8*7>>), do: false def positive?(<<0, _data::8*7>>), do: true def positive?(<<_sign, _data::8*7>>), do: false def same?(<<_first_sign, 0::8*7>>, <<_second_sign, 0::8*7>>), do: true def same?(same, same), do: true def same?(_left, _right), do: false end and the change is like about removing first clause of Example.same?/2 function, right? 1 Like bjorng May 6, 2023, 1:52pm 4 # eiji7: for people not in topic could you also please describe (or link to some article) why <<-0.0/float>> is represented as <<128,0,0,0,0,0,0,0>>? Here is a link to Wikipedia's description: en.wikipedia.org [618px-IEEE_754_Double_Floating_Point_Format] Double-precision floating-point format Double-precision floating-point format (sometimes called FP64 or float64) is a floating-point number format, usually occupying 64 bits in computer memory; it represents a wide dynamic range of numeric values by using a floating radix point. Floating point is used to represent fractional values, or when a wider range is needed than is provided by fixed point (of the same bit width), even if at the cost of precision. Double precision may be chosen when the range or precision of single precision w... Yes, the most significant bit is the sign bit. Your example have the wrong sizes for the segments, but it does seem that you have correctly understood both the current behavior and the new behavior. Here is a corrected Erlang version of your same?/2 function: is_same(<<_:1, 0:63>>, <<_:1, 0:63>>) -> true; is_same(Same, Same) -> true; is_same(_, _) -> false. 3 Likes eiji7 May 6, 2023, 2:21pm 5 # bjorng: Your example have the wrong sizes for the segments Since 8-bit 0 is 00000000 and 128 is 10000000 both examples are good. The <<0>> is <<0:8>> and <<128>> is <<1:1, 0:7>> 1> <<0, 0:56>> =:= <<0.0/float>>. true 2> <<128, 0:56>> =:= <<-0.0/float>>. true 3> <<0:1, 0:63>> =:= <<0.0/float>>. true 4> <<1:1, 0:63>> =:= <<-0.0/float>>. true 5> <<0, 0:56>> == <<0:1, 0:63>>. true 6> <<128, 0:56>> == <<1:1, 0:63>>. true For those who do not understand: 1. My example have: a) 8 bits of 0 + 56 bits of 0 (<<0, 0:56>> or <<0, 0::56>> in Elixir) b) 8 bits of 128 + 56 bits of 0 (<<128, 0:56>> or <<128, 0::56>> in Elixir) 2. Your example have: a) 1 bit of 0 and 63 bits of 0 (<<0:1, 0:63>> or <<0::1, 0::63>> in Elixir) b) 1 bit of 1 and 63 bits of 0 (<<1:1, 0:63>> or <<1::1, 0::63>> in Elixir) So: 1> <<0>> =:= <<0:8>>. true 2> <<128>> =:= <<1:1, 0:7>>. true 3> <<0, 0:56>> =:= <<0:1, 0:63>>. true 4> <<128, 0:56>> =:= <<1:1, 0:7, 0:56>>. true 5> <<1:1, 0:7, 0:56>> =:= <<1:1, 0:63>>. true Also this article may be helpful especially for new developers: trekhleb.dev [01-cover-02] Binary representation of the floating-point numbers | Trekhleb Anti-intuitive but yet interactive example of how the floating-point numbers like -27.156 are stored in binary format in a computer's memory 3 Likes jhogberg May 8, 2023, 6:38am 6 # eiji7: Since 8-bit 0 is 00000000 and 128 is 10000000 both examples are good. The <<0>> is <<0:8>> and <<128>> is <<1:1, 0:7>> No, they work for 0.0 but to be picky they drag in another 7 bits that will either be significant (positive? and negative?) or insignificant (same?) which will give funny results for other numbers. For example, -2.0 would be considered non-negative by negative?, and equal to 2.0 according to same?. 5 Likes eiji7 May 8, 2023, 8:28am 7 ok, now I understand why my code was wrong I was thinking in good way, but I assumed that all first 8 bits are used to store a sign. It's why I asked if it would be always 0 or 128. That's obvious waste of memory, the only relevant is the first bit i.e. <>. The image says more than thousands words! :smiling_imp: image image1000x705 46 KB 2 Likes * Home * Categories * FAQ/Guidelines * Terms of Service * Privacy Policy Powered by Discourse, best viewed with JavaScript enabled Our Sponsors [ericsson] [erlang-sol] [eef] [dashbit] [pragprog] [manning] [wyeworks] [stritzinge] [your-brand] * Contact Us * Help * Back to top (c) Copyright Erlang Forums Terms Privacy & Cookies