1/6が1.0 / 6.0と同じ動作をするプログラミング言語はありますか?


11

数日前にC ++でプログラミングしていたときに、この間違いを犯しました(それを作った歴史があります!)。私のコードの一部では、1/6があり、0.16666666666であると予想していましたが、そうではありません。ご存じのとおり、結果は0-C、C ++、Java、Pythonであり、すべて同じように動作します。

私は自分のFacebookページに投稿しましたが、今では1/6同じような動作をするプログラミング言語があるかどうかについて議論があります1.0/6.0


5
ハスケル。1/6 = 0.16666666666666666
t123

PowerShellは0.166666666666667を生成しますが、1が整数であることに驚きました。期待した値を生成する他の.NET言語がいくつかあると思います。
JohnL

理論的には、それらの数に制限はありません。ここに別のものがあります: Rebol、およびOrca、Redなどの派生物です。 >> 1 / 6->== 0.166666666666667
イズカタ

Luaはこれを行います。単一のNumber型のみがあり、通常はCのdouble型と同じです。
マチャド

Clojure 1/6では実際には1/6(分数型)であり、強制的にDouble1.66666です...
kaoD

回答:


17

誰もがパスカルを忘れましたか?

1/6yields 0.1666666...(サポートされている精度にかかわらず)。

1 div 6 利回り 0

Cルールが間違いであるかどうかは議論の余地があります。オペランドが同じ型であるCのほぼすべての算術演算子は、同じ型の結果を生成します。一貫性のために言わなければならないことがあります。

さらに、Cは主にシステムレベルのコードを対象としているため、ほとんどのCプログラムは浮動小数点をまったく使用しません。一時的に、浮動小数点コードを必要としないプログラムに誤って追加してしまうと、深刻な問題になる可能性がありました。小規模な組み込みシステムの場合は、おそらくまだそうです。これも、Cの主要なターゲットです。

ほとんどのCプログラムでは、整数除算を切り捨てることはおそらくとにかく必要なことです。

1 / 6Cで浮動小数点の結果が得られた場合:

  • それは言語の矛盾です。
  • 標準では、結果に使用する浮動小数点型を任意に選択する必要があります(double自然な選択のように見えるかもしれませんが、の追加の精度を好むかもしれませんlong double
  • 言語はなりまだ整数除算のための操作を持っている必要があります。浮動小数点の加算を実行してから切り捨てることは、おそらく十分ではありません。

C 2種類の除算に別々の演算子を提供できますが、上記の2番目の点は引き続き適用されます。3つの浮動小数点型のどれが結果に使用されますか?必要に応じて浮動小数点除算を取得するのは簡単なので(一方または両方のオペランドに浮動小数点定数を使用するか、一方または両方のオペランドを浮動小数点型にキャストします)、明らかにそうではありませんでしたtはそれを重要だと考えました。

1974年版のCマニュアル(K&Rの初版が発行される4年前)では、リッチーは混乱の可能性についても言及していません。

バイナリ/演算子は除算を示します。乗算と同じタイプの考慮事項が適用されます

これは、両方のオペランドがintorであるchar場合、結果はtypeであると言いますint

はい、一部のCプログラマ、特に初心者にとっては混乱の元になりますが、Cは初心者に優しいことで知られていません。


5
パスカル。Cが間違える前に詳細を取得します。™
メイソンウィーラー

そしてその後、アルゴルは後継者(Cとパスカルの両方が立っている数)よりも改善されました。
AProgrammer

パスカル-詳細を正しく取得する(10倍にするか、10倍にする)
マーティンベケット

1
私はもともと書いたが1.666666...、これは明らかに間違っている。私の不自由な言い訳は、私が書いたパスカルテストプログラムが印刷されていることです1.6666666666666667E-0001
キーストンプソン

16

実際、この動作はPython 3で変更され、期待どおりに動作するようになりました(//整数除算に使用されるようになりました)。


ありがとう。他に考えているプログラミング言語はありますか?多分基本的な家族?
ポウヤ

1
@Pouya:この動作はPascalファミリーの標準です。/常に浮動小数点値を生成し、div整数の除算には別個の演算子()が使用されます。
メイソンウィーラー

13

著名な言語のうち、JavaScript。1.0 / 6.0 = 1/6 = 0.16666666666666666

これは驚くべきことではないと思います。経験則として、言語が整数型と浮動小数点型を区別する場合、2つの整数を除算すると、floatではなく切り捨てられた整数が生成されます。そうでない場合、ほとんどの場合、デフォルトで浮動小数点演算になります。これは、プログラマー側で予想される動作です。

既に述べた個別の整数除算演算子や暗黙的な型キャストなど、ここでも使用できる追加の要素があることに注意してください。


6
これは「経験則」ではありません。これはCのルールであり、Cの間違いを盲目的にコピーした少数の言語です。
メイソンウィーラー

4
@MasonWheeler:FORTRANは「Cの間違いを盲目的にコピー」しましたか?私は個人的に、適切に設計された言語は整数量の切り捨て除算と近似除算に個別の演算子を使用する必要があると考えています(また、値と参照の等式にも)、FORTRANの時代の設計決定はおそらく合理的でした。だからといって、すべての言語が1950年代のFORTRANのように物事を行うべきではありません。
-supercat

3
低レベルの言語はこれらの区別をする必要があります。多くの場合、高レベル/動的言語はそれらなしで実行する方が適切です。これは設計上のトレードオフです。JSに1つの大きな愚かなNumberコンストラクター/型があるだけで感謝していますが、より厳密な型制御なしで高性能の3Dエンジンを記述しようとすると、JSが不足していると感じると思います。JSは他の言語と重複するユーティリティを持っている可能性がありますが、高性能でクロームに近いタイプのものを作成するための重要なものと考える人は誰もいないでしょう。
エリックReppen

2
プログラミング以外の数学では、整数の除算規則を考慮しています。
エリックReppen

5
@MasonWheeler:プログラミングは純粋な数学ではありません。数学的には、1/6は有理数であり、2進浮動小数点数で正確に表すことはできません。唯一の正確な表現は、分子の6倍の分母を持つ比率としてです。
ケビンクライン

7

((1/6)*6)0ではなく1になる言語は数多くあります。たとえば、PL / SQL、多くのBASIC方言、Luaなどです。

偶然にも、これらすべての言語で1/6の結果は.166666667、0.16666666666667などになります。これらの小さな違いを取り除くために、((1/6)* 6)== 1バリアントを選択しました。


7
それは問題ではありません。
ロックマルティ

20
偶然にも、これらすべての言語で1/6の結果は.166666667、0.16666666666667などになります。((1/6)*6)==1これらの小さな違いを取り除くためにバリアントを選択しましたが、一部の人々の数学スキルを過大評価しているようです。
user281377

1
@RocMartíはい、それは本当に
...-MattDavey

1
(1.0 / 6.0)* 6が正確に1に等しいことに驚かされるでしょう!(1.0 / 6.0)の結果の丸めにより、わずかな差が生じます。(ただし、デフォルトで無限精度になる言語がいくつかあります)
Sjoerd

1
@Sjoerd:実際には、それが正確であることはあまり誇張されていません。すべての値が5つの有効数字まで正確である1/11 * 11のシナリオを10進数で考えます。1/11の値は9.0909 * 10 ^ -2です。11を掛けると、丸める前に1つが99.9999 * 10 / -2になります。5つの有効数字に丸めると、結果は1.0000 * 10 ^ 0になります。重要な点は、1/6の仮数が「... 0101010101 ...」であることです。表現の最後のビットが「1」の場合、それを6倍して丸めると1になります。最後のビットがゼロの場合はそうなりません。
-supercat

3

Haskellは、1/6と1.0 / 6.0を同じように0.16666666666666666として扱います。また、1 / 6.0と1.0 / 6も同じ値としてレンダリングされます。

これは、Haskellの基本的な数値型が他の言語とまったく同じではないためです。真の整数除算はやや複雑です。


2

はい、Perlはそうです。ワンライナー

perl -e '$x=1/6;print "$x\n";'

結果は次のとおりです。

0.166666666666667

PHPも同じように機能すると思います。

編集して追加:必要な(ただし十分で1/6 == 1.0/6.0はない)条件は、問題の言語を弱く入力することだと思います。


一体何が弱いタイピング(どういう意味か)が必要なのでしょうか?両方の引数が整数である場合、/を(また)浮動小数点除算を意味するだけで定義します。

1
@delnan - en.wikipedia.org/wiki/Weak_typing私はここで強く型付けされた言語持つことが可能であるかもしれないと仮定し/、自動的に引数の型に応じて、オーバーロードされているが、それは違反のように思える驚き最小の原則に私

2
弱い/強いタイピングは不明確です(wikiも暗示するように)、それを避けて具体的にしてください。私はあなたの定義は暗黙的な変換を禁止していますが、アドホックなポリモーフィズムは禁止していますか?もしそうなら、Haskellを考えてみてください。暗黙の変換はありませんが、かなりよく実行されています(たとえば、99%の時間で動作し、人間が理解できる)数値多型。そして、なぜこれは驚くべきことでしょうか?私が望む正確な精度に応じて、すべての演算子のすべてのインスタンスに多数のドットを追加する必要がある場合、それははるかに驚くべきことです(迷惑とは言いません)。

2
@JackManeyほとんどの新参者にとって、1/2が2つの整数を除算した結果がdoubleである場合よりも1/2が0であることは驚くべきことだと思います。すべての整数は、数学の除算でも閉じられません。また、delnanが指摘しているように、Haskellは、2つの整数で/が整数を生成しない、厳密に型指定された言語の例です。また、Python 3も別の機能です。
sepp2k

1
Haxe言語は強く(推測されますが)型付けされていますが、整数除算はなく、floatのみです。それであなたは行き​​ます。
K.ステフ

2

Squeak Smalltalkでは/、整数でFractionオブジェクトを作成します。したがって、これはfloat除算と同じではありませんが、(1/6)*61を返します。


すべてのSmalltalk-80派生物(つまり、ほぼすべてのSmalltalk)。は現代的な例外の1つです(これは理解可能で、JavaScriptにコンパイルされています)。
ハービー



2

MATLAB。デフォルトでは、数値リテラルはdoubleです。

>> 1/6
ans =
    0.1667

2

Clojureはデフォルトで分数を使用します。1.0 / 6.0とは異なりますが、必要に応じて、floatまたはdouble必要なときに変換できます。

user=> (/ 1 6)
1/6
user=> (* (/ 1 6) 2)
1/3
user=> (pos? (/ 1 6)) ; Is 1/6 > 0?
true
user=> (float (/ 1 6))
0.16666667

1

驚くべきことに、Windows PowerShell (バージョン3)では適切に動作するようです。

PS C:\> 1.0 / 6.0
0.166666666666667

PS C:\> 1/6
0.166666666666667

sepp2kが述べたように、Python 3でも動作するようです。私がREPLですぐに利用できる他の2つの言語、ScalaとRubyは両方とも整数除算を行い、0を生成します。


0

Rexx言語は常に算術的に正しい答えを生成します。例:5/2 = 2.5。Rexxは、十分に活用されていない素晴らしい言語です。理論的には、コンパイラが何を望んでいるかを判断できない場合、正しい計算を行う方が良いですが、これは効率的ではない場合があります。Rexxは//演算子も提供します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.