きしもとです。
# 英語で説明するのがちょっとつらいので、ちょっといったんこちらに
# 書かせてください。

https://github.com/ruby/ruby/pull/1508

こちらの件なのですが、なかださんが示されているように検算を浮動小数の
側に寄せてしまうと、浮動小数にした時に失われている精度のために、どう
やってもうまく説明できなさそうだ、という結論になりそうです。

以下のように、一端BigNum側に寄せて検算する、という例ではどうしょうか?

$ cat fdiv_sample.rb
# fdiv sample

geta_i = 1<<54
geta_f = geta_i.to_f
# sanity check
raise if geta_i.to_f != geta_f
raise if geta_f.to_i != geta_i
raise if geta_i.to_f.to_i != geta_i
raise if geta_f.to_i.to_f != geta_f

x = 3194179693403036
y = 9007199261295557
z = x.fdiv(y)
p(x - z * y)
p((x*geta_i - (z*geta_f).to_i * y).to_f / geta_f)

$ ../trunk/ruby -v fdiv_sample.rb  # trunk
ruby 2.5.0dev (2017-02-02 trunk 57502) [x86_64-freebsd10.3]
0.0
-0.31773970682086544

$ ../fdiv/ruby -v fdiv_sample.rb  # mine
ruby 2.5.0dev (2016-12-30 fdiv_spike 57236) [x86_64-freebsd10.3]
last_commit=round trippable case was already checked before here
0.5
0.182260293542986