PDA

View Full Version : بازه ی داده int (؟)



hosseinam1370
پنج شنبه 13 فروردین 1394, 10:20 صبح
دوستان بازه ی داده int از -32767 تا 32767 هست ، مگه به این معنی نیست که ما مثلا میتونیم از صفر بشماریم و تا 32767 در جهت + , و بشماریم تا -32767 در جهت منفی بریم؟
یعنی حداکثر ارقامش میتونه 5 تا باشه دیگه،

حالا چی شد که با این کد :
#include "stdafx.h"
#include<iostream>
using namespace std;
void main()
{
int shomareDaneshjoii;
shomareDaneshjoii = 911157030;
cout << shomareDaneshjoii;
system("pause");
}

تونستم شماره دانشجوییم رو توش ذخیره کنم؟


البته f10 کردم دیدم که به صورت هگزادسیمال ذخیره میکنه، خوب اون بازه رو هم میتونه به صورت هگزادسیمال ذخیره کنه .


میشه لطف کنید یه توضیحی بدید تا ما هم بفهمیم چخبره.


با تشکر.

chikar
پنج شنبه 13 فروردین 1394, 12:11 عصر
::سیزدهم فروردین، روز طبیعت مبارک::


من هم همین سوال رو دارم، اگر از هدر limit به علاوه دستورات زیر هم استفاده کنید،می بینید که نهایت مقدار باید بین همون بازه ای باشه که جناب hosseinam1370 (http://barnamenevis.org/member.php?306709-hosseinam1370) سوال کردند، پس چرا یک مقدار بزرگ هم درون short int قرار می گیره؟


short int b1 = 9876543211234568880;



#include <limits>
std::cout << "Minimum value for int: " << std::numeric_limits<short int>::min() << '\n';
std::cout << "Maximum value for int: " << std::numeric_limits<short int>::max() << '\n';
::output is::
Minimum value for int: -32768
Maximum value for int: 32767



سوال بعدی ام هم این هست که ، همون طور که می دونید ما در هر بایت می تونیم مقدار بین صفر تا 255 رو بگذاریم، یعنی یک نوع int که چهار بایت هست نهایتا با این تعریف باید این مقدار رو در هر بایت بگیره 255,255,255,255، هر 255 برای یک بایت، پس چرا در 4 بایت از نوع int میشه یک عدد خیلی بزرگتر رو قرار داد؟
توضیحات تکمیلی:
هر بيت می تواند صرفا" شامل يکی از ارقام صفر و يا يک باشد. ( از لحاظ مقداردهی دارای محدوديت هستند و فقط می توان بکمک آنها دو حالت و يا مفهوم را ارائه داد ). از ترکيب هشت بيت ، يک بايت بوجود می آيد. چرا هشت بيت در يک بايت است ؟ با استفاده از هشت بيت در يک بايت ، می توان 256 مقدار ( صفر تا 255 ) را نشان داد.

0 = 00000000 1= 00000001 2 = 00000010 ... 254 = 11111110 255 = 11111111

omid_kma
پنج شنبه 13 فروردین 1394, 17:01 عصر
integer سی ودو بیت هست(البته بستگی به کامپایلر داره )
اغلب کامپایلر های سی یا سی++ برای ذخیره integer از شیوه مکمل 2 (two's complement) استفاده می کنن(البته در استاندارد ذکر نشده ولی این شیوه رایج هست روش هایی دیگری مثل sign magnitude یا one's complement هم وجود داره) .
در این روش اعداد مثبت به شکل باینری معمول ذخیره میشن (تقسیم های متوالی بر 2 ) و برای نمایش اعداد منفی تمام بیت های عدد مثبت بر عکس میشه بعد با یک جمع زده میشه .
پس برای این که اعداد منفی هم نمایش داده باشه از 32 بیت فقط 31 بیت قابل استفاده هست (چون اگر از هر 32 بیت استفاده کنیم زمان برعکس کردن و +1 کردن عدد ممکنه سرریز کنه )
این 31 بیت هر بیت 2 حالت رو ذخیره می کنه که میشه 2^31 حالت که همون عددی هستش که numeric_limits نشون میده(البته باز هم بستگی به کامپایلر داره که از چند بیت برای ذخیره integer استفاده کنه ) پس اون استدلالی که گفتید 4 تا 255 تا میشه قرار داد درست نیست
خروجی این کد رو ببینید بهتر متوجه منظورم میشید :
http://coliru.stacked-crooked.com/a/78b085b9bff20968

integer overflow طبق استاندارد undefine behavior هستش .اون مثالی هم که از short int زدید undefine behavior هست(ویرایش : این خط اشتباه هستش پاسخ های بعد رو ببینید ) وبه معنی کامپایل نشدن کد نیست به این معنی هست که عملکرد کدتوسط استاندارد مشخص نشده و هر اتفاقی میتونه انجام بشه یعنی مثلا اگر چاپش کنید احتمالا یک عدد دیگه چاپ میشه یا اگر داخل for استفاده بشه ممکنه هیچ وقت for تموم نشه

نکته مهمی هم که هست اینه که unsigned integer برخلاف integer زمان استفاده overflow نمی کنن و در صورتی که از محدوده مجاز unsigned بیرون بزنید باقیمانده اون عدد به بزرگترین عدد قابل ذخیره حساب میشه و داخل متغیر گذاشته میشه.



دوستان بازه ی داده int از -32767 تا 32767 هست ، مگه به این معنی نیست که ما مثلا میتونیم از صفر بشماریم و تا 32767 در جهت + و تا بشماریم تا -32767 در جهت منفی بریم؟
یعنی حداکثر ارقامش میتونه 5 تا باشه دیگه،


درست نیست اون عدد هایی که گفتید حداقل بازه هستش که توسط استاندارد ذکر شده و هر کامپایلری باید پوشش بده ولی بازه دقیق int بسته به کامپایلر و معماری سیستم (مثلا 32 یا 64 بیتی بودن ) میتونه بزرگتر باشه اگر از numeric_limits استفاده کنید مقدار دقیقی که قابل ذخیره هست بهتون داده میشه. (مثلا داخل کامپایلر من و احتمالا شما یک عدد 10 رقمی هستش)(کدی که بالا گذاشتم رو ببینید)



چرا هشت بيت در يک بايت است ؟

دلایل تاریخی و سخت افزاری داره این صفحه ویکیپدیا توضیحات جالب و کاملی در این مورد داره : https://en.wikipedia.org/wiki/Byte

rahnema1
پنج شنبه 13 فروردین 1394, 18:14 عصر
سلام
در عباراتی که تبدیل ضمنی انجام می گیره مثل مقداردهی اولیه و یا انتساب، و این در صورتی باشه که نوع مقصد علامتدار باشه جواب عبارت بستگی به پیاده سازی داره
مثل این مثال

short int b1 = 9876543211234568880;

ممکنه این جور پیاده سازی شده باشه که بیشترین مقدار short در b1 قرار بگیر و یا اینکه از باقیمانده تقسیم اون عدد استفاده بشه.

omid_kma
پنج شنبه 13 فروردین 1394, 18:47 عصر
سلام
در عباراتی که تبدیل ضمنی انجام می گیره مثل مقداردهی اولیه و یا انتساب، و این در صورتی باشه که نوع مقصد علامتدار باشه جواب عبارت بستگی به پیاده سازی داره
مثل این مثال

short int b1 = 9876543211234568880;

ممکنه این جور پیاده سازی شده باشه که بیشترین مقدار short در b1 قرار بگیر و یا اینکه از باقیمانده تقسیم اون عدد استفاده بشه.

چیزی که در استاندارد سی++ هست اینه که integer literal ها داخل نوع متغیری قرار میگیرند که فضای کافی داشته باشه مثلا در این مثال 987... داخل long long قابل ذخیرست پس اول در long long ذخیره میشه . بعد long long به short تبدیل میشه که همون طوری که شما گفتید imlpementation defined هستش .

البته درCچون داشتن فضا مهم نیست و integer literal فقط داخل integer قابل ذخیرست چون مقدار بزرگتر از سایز int هست undefine behavior هستش (احتمالا هم کامپایل ارور داده میشه )

hosseinam1370
پنج شنبه 13 فروردین 1394, 20:16 عصر
یکم تخصصی گفتید شما ، فهمیدنش برام یکم سخت شد، حالا اون چیزهایی که من فهمیدم و میگم ، شما یه بزرگواری کنید اصلاحش کنید،
1_ اون بازه ای که گفتم حداقل های یک int هست که در تمام زبان های برنامه نویسی باید رعایت بشه.
2_اگه مثلا با داده int من بیام شماره دانشجوییم که 911157030 هست رو ذخیره کنم، به این معنی هست که من میتونم از 1 تا 911157030 بشمارم.
3_با توجه به اینکه کامپایلرهای مختلف بیت یا بایت متفاوتی به int میدن، ممکنه من نتونم شماره دانشجوییم (911157030) را در آن کامپایلر ذخیره کنم.
4_اگه من بیام برای سیستم عامل 64 بیت بر فرض مثال برنامه ای بنویسم که با یه داده int شماره دانشجوییم رو بتونم تو اون متغییر ذخیره کنم ، اگه همون برنامه رو ببرم تو یه سیستم عامل 32 بیت نصب کنم ، ممکنه نتونه شماره دانشجوییم و ذخیره کنه و به اصطلاح بگن برنامه باگ داره!! درسته؟
5_دوستان من اگه بخام طبق یه استاندارد واحد برای همه سیستم عاملهای 32 یا 64 یا دیگر کامپیالر ها از مقدار دقیق بازه های داده استفاده کنم ، باید چیکار کنم؟

با تشکر.

rahnema1
پنج شنبه 13 فروردین 1394, 21:20 عصر
چیزی که در استاندارد سی++ هست اینه که integer literal ها داخل نوع متغیری قرار میگیرند که فضای کافی داشته باشه مثلا در این مثال 987... داخل long long قابل ذخیرست پس اول در long long ذخیره میشه . بعد long long به short تبدیل میشه که همون طوری که شما گفتید imlpementation defined هستش .

البته درCچون داشتن فضا مهم نیست و integer literal فقط داخل integer قابل ذخیرست چون مقدار بزرگتر از سایز int هست undefine behavior هستش (احتمالا هم کامپایل ارور داده میشه )

فکر کنم فرق چندانی بین c و ++c نمی کنه به هر حال اگه در long long جا نشد ممکنه داخل یک نوع extended جا بگیره در غیر این صورت اگه اون عدد ثابت در هیچ کدام از انواع ذکر شده قابل نمایش نباشه در ++c نتیجه خطای سینتکس میشه اما در c یک عدد صحیح بدون نوع میشه!

rahnema1
پنج شنبه 13 فروردین 1394, 21:23 عصر
یکم تخصصی گفتید شما ، فهمیدنش برام یکم سخت شد، حالا اون چیزهایی که من فهمیدم و میگم ، شما یه بزرگواری کنید اصلاحش کنید،
1_ اون بازه ای که گفتم حداقل های یک int هست که در تمام زبان های برنامه نویسی باید رعایت بشه.
2_اگه مثلا با داده int من بیام شماره دانشجوییم که 911157030 هست رو ذخیره کنم، به این معنی هست که من میتونم از 1 تا 911157030 بشمارم.
3_با توجه به اینکه کامپایلرهای مختلف بیت یا بایت متفاوتی به int میدن، ممکنه من نتونم شماره دانشجوییم (911157030) را در آن کامپایلر ذخیره کنم.
4_اگه من بیام برای سیستم عامل 64 بیت بر فرض مثال برنامه ای بنویسم که با یه داده int شماره دانشجوییم رو بتونم تو اون متغییر ذخیره کنم ، اگه همون برنامه رو ببرم تو یه سیستم عامل 32 بیت نصب کنم ، ممکنه نتونه شماره دانشجوییم و ذخیره کنه و به اصطلاح بگن برنامه باگ داره!! درسته؟
5_دوستان من اگه بخام طبق یه استاندارد واحد برای همه سیستم عاملهای 32 یا 64 یا دیگر کامپیالر ها از مقدار دقیق بازه های داده استفاده کنم ، باید چیکار کنم؟

با تشکر.

شما بسته به اندازه عدد یکی از انواعی که در لینک زیر اومده انتخاب کنید:
http://en.cppreference.com/w/cpp/language/types

chikar
پنج شنبه 13 فروردین 1394, 23:56 عصر
پس اون استدلالی که گفتید 4 تا 255 تا میشه قرار داد درست نیست
خروجی این کد رو ببینید بهتر متوجه منظورم میشید :
http://coliru.stacked-crooked.com/a/78b085b9bff20968



مطلبی که در مورد مثال من گذاشتید یعنی undefine behavior منطقی است اما راجع به نهایت مقدار 255 در هر بایت رو من هنوز کاملا توجیه نشدم، شما به همون لینک مثال خودتون در بالا مراجعه کنید و مقدار bitset رو از 32 به 8 تقلیل بدید و در بخش showBits هم مقدار 256 رو قرار بدید، مشاهده خواهید کرد که 8 بیت برابر صفر است و برای نمایش عدد 256 باید از 16 بیت یا 2 بایت استفاده شود، پس منطق این مساله چی میشه! مرسی

---------------------------


سلام
در عباراتی که تبدیل ضمنی انجام می گیره مثل مقداردهی اولیه و یا انتساب، و این در صورتی باشه که نوع مقصد علامتدار باشه جواب عبارت بستگی به پیاده سازی داره


چرا اصلا باید مقداری فراتر از مقدار تعیین شده، قابل انتساب به یک متغیر باشه، که در نهایت هم وابسته به پیاده سازی و بروز خطا و نتیجه غیرقابل پیش بینی می شه!

omid_kma
جمعه 14 فروردین 1394, 00:14 صبح
فکر کنم فرق چندانی بین c و ++c نمی کنه به هر حال اگه در long long جا نشد ممکنه داخل یک نوع extended جا بگیره در غیر این صورت اگه اون عدد ثابت در هیچ کدام از انواع ذکر شده قابل نمایش نباشه در ++c نتیجه خطای سینتکس میشه اما در c یک عدد صحیح بدون نوع میشه!
خب قبول دارید که گذاشتن این عدد صحیح بدون نوع داخل متغیر باعث overflow میشه ؟
برای اطمینان int a=12345678999 رو داخل این سایت با استفاده از یک کامپایلر سی مثل gcc کامپایل کنید http://coliru.stacked-crooked.com/a/43929a231bbdde71
این وارنینگ داده میشه : warning :overflow in implicit constant conversation
در حالی که مثلا کامپایلر clang وارنینگ تبدیل long به int میده :http://coliru.stacked-crooked.com/a/1277073597441070

فکر نمی کنم overflow کردن و نکردن تفاوت کمی باشه.

rahnema1
جمعه 14 فروردین 1394, 06:28 صبح
چرا اصلا باید مقداری فراتر از مقدار تعیین شده، قابل انتساب به یک متغیر باشه، که در نهایت هم وابسته به پیاده سازی و بروز خطا و نتیجه غیرقابل پیش بینی می شه!

ببینید نتیجه اینجا غیر قابل پیش بینی نیست. یعنی باید به نحوه پیاده سازی مراجعه کنیم تا ببینیم چه اتفاقی می افته و لزوما خطا هم نیست
این موارد Implementation-defined در زبان c و ++c همون طور که قبلا بحث کرده بودیم زیاد هست برعکس زبانی مثل جاوا که سعی کرده این جور موارد را از ساختار زبانش برداره
اما فلسفه اینکه چرا باید انتساب عددی بزرگ مجاز باشه نمیدونم.

rahnema1
جمعه 14 فروردین 1394, 06:30 صبح
خب قبول دارید که گذاشتن این عدد صحیح بدون نوع داخل متغیر باعث overflow میشه ؟

شاید به اونجا نکشه که بدون نوع بشه مثلا در یک نوع extended که ظرفیت کافی داشته باشه ذخیره بشه
در واقع ثابت عددی بدون نوع، مجاز نیست و همون خطای سینتکس هست چون در استاندارد c اشاره کرده هر ثابت، باید «نوع» داشته باشد.


برای اطمینان int a=12345678999 رو داخل این سایت با استفاده از یک کامپایلر سی مثل gcc کامپایل کنید http://coliru.stacked-crooked.com/a/43929a231bbdde71
این وارنینگ داده میشه : warning :overflow in implicit constant conversation
در حالی که مثلا کامپایلر clang وارنینگ تبدیل long به int میده :http://coliru.stacked-crooked.com/a/1277073597441070

فکر نمی کنم overflow کردن و نکردن تفاوت کمی باشه.

فکر کنم overflow در زمینه عملیات حسابی معنا پیدا می کنه مثل مثال زیر
که در جمع overflow اتفاق می افته

int a = 2147481000;
int b = 2147481000;

int c = a + b;


اینجا a و b که جمع میشن overflow میشه اما overflow به خاطر این نیست که انتساب رخ داده
به خاطر این هست که جمع مشکل داره یعنی اگر هر دو عدد a و b برابر long long بودند ما overflow نداشتیم!

omid_kma
جمعه 14 فروردین 1394, 11:22 صبح
شاید به اونجا نکشه که بدون نوع بشه مثلا در یک نوع extended که ظرفیت کافی داشته باشه ذخیره بشه

فرق C و C++‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎ ‎‎‎ همین جاست در C متغیر بصورت اتوماتیک داخل نوع extended ذخیره نمیشه .


در واقع ثابت عددی بدون نوع، مجاز نیست و همون خطای سینتکس هست چون در استاندارد c اشاره کرده هر ثابت، باید «نوع» داشته باشد.

شاید همین طور باشه .ولی این کاری نیست که کامپایلر gcc انجام میده .


فکر کنم overflow در زمینه عملیات حسابی معنا پیدا می کنه

ببینید بحث اینجاست که در C وقتی مثلا مینویسید int a =999999999999999 این 999... بر خلاف ++C نوعش long نمیشه . زمان انتساب یک عدد "بدون نوع" بزرگ رو میخواهید بزارید داخل int که از نظر من overflow و undefine behavior هستش
فکر هم نمی کنم جایی گفته شده باشه overflow فقط مخصوص زمان عملیات حسابی باشه.



شما به همون لینک مثال خودتون در بالا مراجعه کنید و مقدار bitset رو از 32 به 8 تقلیل بدید و در بخش showBits هم مقدار 256 رو قرار بدید، مشاهده خواهید کرد که 8 بیت برابر صفر است و برای نمایش عدد 256 باید از 16 بیت یا 2 بایت استفاده شود، پس منطق این مساله چی میشه!

منطق چه مساله ای ؟
char میتونه 256 تاعدد ذخیره کنه از -127-128 پس طبیعتا 256 قابل ذخیره در char نیست.
ضمنا دلیل صفر شدن هم overflow نیست اگر ورودی تابع رو هم char کرده باشید . وقتی که 256 رو میفرستید به تابع تبدیل از int به char داریم که implementation defined هستش و بنظر میرسه داخل کامپایلرتون به این شکل تعریف شده که باقیمانده عدد به 128گذاشته بشه .

chikar
جمعه 14 فروردین 1394, 13:07 عصر
مثل که اصلا سوال من رو متوجه نشدید
ببینید من منظورم این نیست، که چرا هشت بیت میشه یک بایت یا چرا در یک بایت میشه 0 تا 255 را ذخیره کرد، یا اصلا از overflow حرفی نزدم، من فقط یه سوال واضح دارم
کد های زیر رو ببینید

std::cout << "Maximum value for int: " << std::numeric_limits<int>::max() << '\n';
std::cout << "size of int:: " <<sizeof(int)<< '\n';

::output is::
Maximum value for int: 2147483647
size of int:: 4



همون طور که می بینید نوع int که 4 بایت هست ماکزیمم مقدار 2147483647 این رو قبول می کنه، ولی با توجه به 4 بایت بودن int این نوع باید ماکزیمم 255255255255 این بازه رو بپذیره، آیا دلیل خاصی هست که در 4 بایت مقدار کمتری از 4 تا 255 یعنی 2147483647 قرار می گیره؟
مخاطب پرسش من هم فقط آقای omid_kma نیست، هر کس دلیلش رو متوجه است لطف کنه پاسخ بده

omid_kma
جمعه 14 فروردین 1394, 15:00 عصر
ببینید این شیوه ای که شما می گید با روش معمول ذخیره اعداد باینری متفاوته شیوه معمول based_2 و بر مبنای توان های 2 هست
یعنی مثلا عدد 1111101011111010 در مبنای باینری معادل این عدد در مبنای 10 میشه : 0^2*0 + 1^2*1 + 2^2*0 +3^2*1 +..... = 64250
ولی با شیوه شما همین عدد میشه 250250
که این یعنی با روش شما عدد باینری که یک integer تولید می کنه کاملا متفاوت میشه .
خب حالا فرض کنید میخواهیم 2 تا عدد رو با هم جمع بزنیم :
چیزی که الان و جود داره این هست که هر 2 تا عدد به باینری تبدیل میشن داخل رجیستر های سی پی یو ذخیره میشن و بوسیله مدار سخت افزاری جمع زننده(full adder) که بر اساس این شیوه based_2 عمل می کنه جمع زده میشن
حالا اگر همین جمع زدن رو بخواهیم روی اعدادی که با شیوه شما تبدیل به باینری میشن انجام بدیم جواب اشتباه داده میشه چون جمع زننده سخت افزاری بر اساس مبنای 2 کار می کنه نه شیوه شما یعنی این که مثلا 250250 + 250250 رو اگر با روش شما به شکل باینری ذخیره کنیم با استفاده از ساختار کامپایلر و cpu فعلی جمع بزنیم عدد خروجی میشه : 128500 که اشتباه هست .
برای این که با شیوه شما درست کار کنه 2 کار باید انجام بشه :
1_ کامپایلر باید بتونه عدد دسیمالی که داخل کد نوشته میشه رو زمان اجرا یا کامپایل به جای based_2 بر اساس روش شما ذخیره کنه یعنی نیاز هست که کامپایلر باز نویسی بشه .
2_ مورد مهمم تر این که باید معماری cpu عوض بشه و مدار های مربوط به جمع زدن , ضرب کردن و ... کاملا عوض بشن که عملا امکان این کار وجود نداره(مداری که با این شیوه ساخته بشه بدلیل پیچیدگی بیشتر عملیات ها نسبت به مبنای 2 کند تر هم هست)

توی برنامه نویسی و سخت افزار همیشه این توازن بین حجم قابل ذخیره و سرعت و هزینه تولید وجود داره شاید با شیوه شما اعداد بزرگتری قابل ذخیره باشه ولی در عوض سرعت کمتر و هزینه بیشتر میشه .

برای درک بیشتر این مطالب پیشنهاد می کنم این 2 تا کتاب رو مطالعه کنید:
http://www.amazon.com/Fundamentals-Logic-Design-Charles-Roth/dp/1133628478/ref=sr_1_2?s=books&ie=UTF8&qid=1428059213&sr=1-2&keywords=fundamental+of+logic+circuit
http://www.amazon.com/gp/product/0124077269/ref=s9_psimh_gw_p14_d0_i2?pf_rd_m=ATVPDKIKX0DER&pf_rd_s=desktop-1&pf_rd_r=170WB9NZEQ4MFP8B6WEE&pf_rd_t=36701&pf_rd_p=1970559082&pf_rd_i=desktop

hosseinam1370
جمعه 14 فروردین 1394, 15:36 عصر
دوستان من صبح امروز این تبدیل رو انجام دادم ، و بازه ی int رو بدست آوردم،ببینید(تصویر در ضمیمه):




که از تبدیلات انجام شده با مبنا 16 ، بازه ی int ، در صورت بدونه علامت بودن، از صفر هست تا 4,294,967,295 و در صورتی که int علامتدار تعریف شده باشد بازه ی آن از -2147483648 تا 2147483647 خواهد بود.
که با کد زیر میتونید بازه رو ببینید :
void main()
{
unsigned int a = 4294967295;

cout << a;
system("pause");
}

اگه در کد بالا شما جای 5 بزارید 6 ، یعنی +1 کنید 4,294,967,295 رو ، متوجه سرریز(overflow) شدن int میشید.

و همونطور که شما دوستان میدونید، شما میتونید عملیات + ، - ، * ، / رو در بازه ی از صفر تا 4,294,967,295 در بدونه علامت و در بازه ی -2147483648 تا 2147483647 با علامت ، رو انجام دهید.

کد زیر عملیات جمع رو نشان میدهد ، که اگه یکی از متغییر ها رو +1 کنید ، داده int سرریز(overflow) میشود:
void main()
{
int a = 2147483647;
int b = 2147483648;

unsigned int c = a + b;
cout << c;
system("pause");
}


کاربر chikar با دیدن عکس میتونید بفهمید که ربطی به اعداد 255.255.255.255 نخواهد داشت، منظورم اینه که اینجا بحث ارزش مکانی این 255 هست، با ذکر یک مثال امیدوارم بتونم منظورمو انتقال بدم،

شما عدد 137 رو فرض کنید، رقم 7 ارزش یکان رو داره ، رقم 3 ارزش دهگان رو داره ، رقم 1 ارزش صدگان رو داره، خوب با وجود این ارزش های مکانی هست که ما میتونیم بگیم 137 یا 138 یا حداکثر عدد سه رقمی 999 ،
یعنی الان اگه شما بیاید این ارزش های مکانی رو نادیده بگیرید ، مثلا 7 رو یکان و 3 رو یکان و 1 رو یکان ، شما فقط به اعداد 1 تا 9 دسترسی دارید .

اینجا برای 255 هم همینه (شما هر 255 را یک رقم مثله مثال بالا بپندارید، مثلا 255 اول ارزش رقمی یکان، 255 دوم ارزش مکانی دهگان، و همینطور الی آخر) و حالا ارزش مکانی این 255 ها به این صورته:
نکته :همونطور که مبنای 8 رقم هاش از 0 تا 7 هست، همونطور که مبنای 10 رقم هاش از 0 تا 9 هست و همانطور که مبنای 16 رقم هاش از 0 تا 15 هست ، پس میتونیم بگیم مبنای 256 رقم هاش از 0 تا 255 هست، (برای ثبت ارزش مکانی به این تبدیل نیاز داریم).
خوب حالا 255،255،255،255 رو در مبنای 256 و برای بدست آوردن بازه متغییرش ، اینگونه محاسبه میکنیم :
(255*256^3)+(255*256^2)+(255*256^1)+(255*256^0)=42 94967295

با دیدن عکس و کمی فکر کردن کل موضوع جا میاوفته.
امیدوارم که منظورمو فهمیده باشید.



حالا سوال اینه که آیا همه کامپایلر ها و همجا و هر زبانی متغییر int دارای 4 بایت حافظه هست ، یا نه؟
موفق باشید.

chikar
جمعه 14 فروردین 1394, 17:13 عصر
ببینید این شیوه ای که شما می گید با روش معمول ذخیره اعداد باینری متفاوته شیوه معمول based_2 و بر مبنای توان های 2 هست
یعنی مثلا عدد 1111101011111010 در مبنای باینری معادل این عدد در مبنای 10 میشه : 0^2*0 + 1^2*1 + 2^2*0 +3^2*1 +..... = 64250
ولی با شیوه شما همین عدد میشه 250250


مرسی این چیزی بود که می خواستم
در اصل کامپایلر 4 بایت را 4 تا 8 بیت جدا جدا در نظر نمی گیره بلکه 4 بایت رو یه مقدار 32 بیتی در نظر می گیره، وقتی همون نهایت مقداری رو که کامپایلر برای بازه int گفته یعنی 2147483647 رو به مبنای 2 بردم، دقیقا 31 بیت مقدار 1 رو به من نشون می ده و با توجه به تعریف شما اون یک بیت هم برای اعداد منفی کنار گذاشته می شه
2(1111111111111111111111111111111) = 10(2147483647)

chikar
جمعه 14 فروردین 1394, 17:24 عصر
ضمیمه 129986 (http://barnamenevis.org/attachment.php?attachmentid=129986)
کاربر chikar با دیدن عکس میتونید بفهمید که ربطی به اعداد 255.255.255.255 نخواهد داشت، منظورم اینه که اینجا بحث ارزش مکانی این 255 هست، با ذکر یک مثال امیدوارم بتونم منظورمو انتقال بدم،

شما عدد 137 رو فرض کنید، رقم 7 ارزش یکان رو داره ، رقم 3 ارزش دهگان رو داره ، رقم 1 ارزش صدگان رو داره، خوب با وجود این ارزش های مکانی هست که ما میتونیم بگیم 137 یا 138 یا حداکثر عدد سه رقمی 999 ،
یعنی الان اگه شما بیاید این ارزش های مکانی رو نادیده بگیرید ، مثلا 7 رو یکان و 3 رو یکان و 1 رو یکان ، شما فقط به اعداد 1 تا 9 دسترسی دارید

با دیدن عکس و کمی فکر کردن کل موضوع جا میاوفته.
امیدوارم که منظورمو فهمیده باشید.





عکس که نمایش داده نمیشه، ولی متوجه شدم، مطلب آقای omid_kma رو شما به یه شیوه دیگه گفتید،منظورتون رو متوجه شدم، مرسی خوب بود

rahnema1
جمعه 14 فروردین 1394, 22:04 عصر
جهت اثبات مطالبی که گفتم متن استاندارد زبان c و ++c را میذارم که به ترتیب در دو فایل pdf به نام n1570 و n3242 قرار داره گرچه هزار تا سند هم بیارم ظاهرا فایده نداره



فرق C و C++‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎ ‎‎‎ همین جاست در C متغیر بصورت اتوماتیک داخل نوع extended ذخیره نمیشه .

در استاندارد c اینجور نوشته و نوع extended را ذکر کرده همون جور که در ++c هم ذکر شده:
ص 64
If an integer constant cannot be represented by any type in its list, it may have an extended integer type, if the extended integer type can represent its value. ...


شاید همین طور باشه .ولی این کاری نیست که کامپایلر gcc انجام میده .

اگه تردید دارید مدرکش را مثل قبلی واستون بذارم. فکر کنم لازمه وقتی روی این مسائل بحث می کنیم مدرک و ملاک ما استاندارد باشه نه رفتار یک کامپایلر


ببینید بحث اینجاست که در C وقتی مثلا مینویسید int a =999999999999999 این 999... بر خلاف ++C نوعش long نمیشه . زمان انتساب یک عدد "بدون نوع" بزرگ رو میخواهید بزارید داخل int که از نظر من overflow و undefine behavior هستش

تقریبا همون قواعدی که در c هست در ++c هم هست شما ص 25 از استاندارد ++c و ص 64 از استاندارد c هم ببینید که ثابت مذکور در چه نوعی ذخیره میشه مخصوصا اون جدولها را ببنید که دقیقا مطابق هم هستند
در c میشه بدون نوع و گفته هر ثابت عددی باید نوع داشته باشه این یعنی چی؟ یعنی خطا. کامپایلر باید error بده نه undefined behavior چون کاملا ذکر شده که ثابت باید نوع داشته باشه


فکر هم نمی کنم جایی گفته شده باشه overflow فقط مخصوص زمان عملیات حسابی باشه.


تعریف overflow که موجب undefined behavior میشه را از استاندارد ++c ص 101 در قسمت expression در پاراگراف پنجم نقل قول می کنم

If during the evaluation of an expression, the result is not mathematically defined or not in the range of
representable values for its type, the behavior is undefined. [ Note: most existing implementations of C++
ignore integer overflows. Treatment of division by zero, forming a remainder using a zero divisor, and all
floating point exceptions vary among machines, and is usually adjustable by a library function. — end note]

گفته یک expression در این حالت دچار undefined behavior می شه
حالا expression چیه؟
ص 101 پند پنجم
An expression is a sequence of operators and operands that specifies a computation
یعنی توالی عملگرها و عملوندها که یک «محاسبه» را مشخص می کند اگر انتساب ساده باشه هیچ محاسبه ای صورت نگرفته
بنابراین در استاندارد گفته شده که overflow در زمینه محاسبه هست نه انتساب ساده