Jump to page: 1 2
Thread overview
uint türünde doğru çalışmayan abs()
Oct 05, 2019
Salih Dinçer
Oct 05, 2019
Salih Dinçer
Oct 05, 2019
Salih Dinçer
Oct 06, 2019
kerdemdemir
Oct 06, 2019
Salih Dinçer
Oct 10, 2019
kerdemdemir
Nov 01, 2019
Salih Dinçer
October 05, 2019

Merhaba,

Aşağıdaki basit denemeyi tüm DMD sürümlerinde derlediğimde yanlış sonuç elde ediyorum. Ama işaretli veya virgüllü olsun/olmasın uint dışında tüm türlerde abs() doğru çalışıyor:

/* http://run.dlang.io

All versions: Success with output:
-----
4294967294
2
*/
import std.stdio, std.math : abs;

void main()
{
   uint[] sub = [ 3, 5 ];

   writeln(abs(sub[0] - sub[1]));
   writeln(sub[1] - sub[0]);
}

Bu bir bug olabilir mi?

Sevgilerimle..

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 05, 2019

Düzeltme: Sorun sadece 'uint' ve 'ulong''da da oluyormuş. Aslında sonuç ulong.max-1 = 18446744073709551615 olarak çıkıyor.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 05, 2019

Sorunu, typeof() ile incelediğimde std.math içindeki mutlak işlevinin kendisinden küçük türlerde int döndürmeye zorladığını, büyüklerde ise aynı türü yansıttığını ama hatalı hesapladığını gördüm:

ushort ile denenmiş bir çıktı:
abs() type: int, Value: 2
mut() Type: uint, Value: 4294967294

Sorunun neden kaynaklandığına emin olamadım; ta ki kendi yazdığım işlev ile C'dekini karşılaştırana dek! Eğer aşağıdaki yazdığım kodun 2. satırını // ile gizlerseniz (toggle marking) sorunun C'de var olmadığını görürsünüz.

import std.stdio;
import std.math;/*
import core.stdc.stdlib : abs;//*/

uint mut(int x)
{
	return (x>0?x:(x|typeof(x).max)-(x-1));
}

ulong mut(long x)
{
	return (x>0?x:(x|typeof(x).max)-(x-1));
}

void main()
{
   uint[] sub = [ 346367643, 54374255 ];
   // s = 291.993.388
   auto s1 = abs(sub[1] - sub[0]);
   auto s2 = mut(sub[1] - sub[0]);

   writefln("abs() type: %s, Value: %d",
             typeof(s1).stringof, s1);
   writefln("mut() Type: %s, Value: %d",
             typeof(s2).stringof, s2);
}/* Output:
abs() type: uint, Value: 4002973908
mut() Type: uint, Value: 291993388
*/

Özetle, D'deki abs() iyi çalışmıyor ama long türü için de C kütüphanesindeki sanırım desteklemiyor. Benim yazdığım mut() ise D'nin eksiğini kapıyor (öyleyse bu bir bug!) ama byte ve short ile çalıştıramadım! :rolleyes:

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 05, 2019

Şaşırtıcı ama hata değil. Hangi işlemin sonucunun hangi türden olacağı oldukça karmaşık kurallarla belilenir. (D bunları C'den almıştır ve C++'ta da aynıdır). Bu konuyla tam ilgili olmasa da, tamsayı terfileri konusu da aynı derecede şaşırtıcı olabilir:

http://ddili.org/ders/d/tur_donusumleri.html#ix_tur_donusumleri.int%20terfisi

Buradaki konu, uin'in sıfırdan küçük değer taşıyamamasıdır. -2 olmasını beklediğimiz değerin bit karşılığı ne ise, onun uint olarak taşıdığı değeri görüyoruz. :/

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 06, 2019

Bence abs 'ın davranışı yanlış değil.

Durumun sebebi benim gördüğüm kadarıyla

import std.stdio;
import std.math;

auto foo(T)( T val )   // -> https://dlang.org/library/std/math/abs.html
{
   writeln(val);  //--> 4294967294 yazdırıyor
}

void main()
{
	uint x = 3;
   uint y = 5;
   foo( x - y);
}

Yani abs fonksiyonu hiç bir zaman geçirli girdileri almıyor bu durumda herzaman 4294967294 gibi bir değer alıyor.Bu değer uint, ushort, ulong için değişicekdir ama her zaman çöp bir değer olacaktır.
Türkçesini bulamadım şu deyimin ama durum bence "Garbage in garbage out".

Erdem

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 06, 2019

Doğru bir karşılaştırma değil çünkü C'de unsigned parametre alan abs() işlevi yok. O yüzden, bizim uint değerler int'e dönüştürüldükten sonra C'nin abs()'ine gönderiliyorlar.

Tabii ki D'nin abs'inde hata olabilir ama dilin hangi kuralıyla çeliştiğini de göstermek gerek.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 06, 2019

Burada bence biri temel 2 sorun var:

1.'si matematik: Siz eğer işaretli sonuç üretecekseniz işleve giren sayılar int veya long olmalı ki abs() bunu kısmen yapıyor. Eğer mut()’a da işaretsiz verirseniz o da başarısız oluyor!

**2'si ise teknik: **abs() işlevinden geçirince (onun mutlak positive olacağını bile bile!) neden hala size_t türü bir işaretsiz değer döndüremiyorsun kardeşim diye sormazlar mı :)

Eeee, ben sordum ve aynı dilin olanakları ile uint veya ulong döndürdüm. Çünkü bana int.max yetmiyor, en azından uint.max'a kadar işlem yapabilmem gerekiyor.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 07, 2019

Alıntı (Salih Dinçer):

>

Siz eğer işaretli sonuç üretecekseniz işleve giren sayılar int veya long olmalı ki

Onu sağlamak için abs() bir şablon kısıtlaması[1] kullanabilirmiş ama o zaman da abs()'i çağıran olasılıkla başka bir şablon, çağırmadan önce std.traits.isSigned ile denetlemek zorunda kalırdı. Oysa, unsigned türleri de kabul ederek abs() daha kullanışlı oluyor.

(Bu arada, Erdem'in hatırlattığı gibi, bu sorun abs() ile ilgili değil.)

Alıntı:

>

abs() işlevinden geçirince (onun mutlak positive olacağını bile bile!) neden hala size_t türü bir işaretsiz değer

Yani, en büyük tamsayı türünü döndürsün diyorsun, değil mi? (Eğer gerçekten öyleyse, ulong'u seçmek daha doğru olur çünkü size_t 32 bit olabilir.)

Bu fikre de şöyle karşı çıkılabilir: abs()'e ushort verdiysem sonucun ushort olmasını beklerim.

Ama gerçekten, abs()'i bir kenara bırakalım ve 0U - 1 ifadesinin sonucuyla ve türüyle ilgilenelim. Asıl karışıklık orada. ;)

Ali

[1] http://ddili.org/ders/d/sablonlar_ayrintili.html#ix_sablonlar_ayrintili.k%C4%B1s%C4%B1tlama,%20%C5%9Fablon

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 10, 2019

Ali abi

" 0U - 1" konusunu ayri baslikta(veya bu baslik altinda) ele alirsan severek okurum valla.

Erdem

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 10, 2019

Herkesin bildiğinden farklı bir şey değil. :) 0U - 1 ifadesinin türü, tamsayı terfilerine (integer promotions) uygun olarak uint oluyor ve uint negatif değer taşıyamadığından da değeri 4294967295 oluyor.

Belki öteki türlü yazılsa daha şaşırtıcı: 0 - 1U deyince 0 int olduğundan sonucun -1 olması beklenebilir ama değil. Sonuç yine 4294967295.

Veya, -1'e 0 ekleyelim: -1 + 0U == 4294967295.

Delilik! :) Ama kurallar belli ve bu davranışlar da o kurallara uygun.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

« First   ‹ Prev
1 2