Чи є номери, які не можуть бути представлені в базі 10, але можуть бути представлені у базі 2?


42

C#має decimalтип, який використовується для чисел, які потребують точного подання в базі 10. Наприклад, 0.1не може бути представлений у базі 2 (наприклад, floatта double) і завжди буде наближенням, коли зберігається у змінних, що мають ці типи.

Мені було цікаво, чи можливий і зворотний факт. Чи є номери, які не можуть бути представлені в базі 10, але можуть бути представлені у базі 2 (у такому випадку я б хотів використовувати floatзамість а, decimalщоб обробити їх)?


14
+1 до питання, але чи дійсно тут застосовано тег c # ? Інші мови також мають десятковий тип.
Патрік М

1
@Max: В якості вправи пропоную вам перетворити вручну перетворення числа 2 на базу 10. Наприклад, щоб обчислити значення 0.11_b2, випишіть його як 0.5 + 0.5 * 0.5. Чи є якийсь крок, який може вийти з ладу або призвести до повторної десяткової? Особисто я вважаю, що ця вправа чудово справляється з інтуїцією щодо базових 2 чисел. Я гадаю, що можна було б піти на крок далі і перетворити цю вправу на доказ конструкції.
Брайан

Ах, але ви помиляєтесь. 1/1010
Xavier J

3
@Ramhound Враховуючи обмеження пам’яті, двійковий файл може представляти 0.0999999....998..саме, але не повне число 0.1- наближення, наприклад, округлення до найближчої скарбниці 0.100, є проблемою щодо впровадження, яка передбачає не показ усіх цифр та їх округлення.
Ізката

1
Що ж, можна придумати механізм кодування FP, який дозволяє точно "представити" 0,1 ". Таке кодування просто зміщується навколо наборів діапазонів FP, ніж можна і не може бути представлено.
Мартін Джеймс

Відповіді:


104

Ось ключ до вашої проблеми: 10це продукт 2і 5. Ви можете уявити будь-яку кількість разів в базі 10 десяткових знаків , що становить до * 1/2 п * 1/5 м , де k, nі mцілі числа.

Альтернативно - фразове значення - якщо число nв 1 / n містить коефіцієнт, який не входить до числа факторів бази, число не може бути представлене точно у фіксованій кількості цифр у двійковій / десятковій / незалежно від розширення цього номер - він буде мати повторювану частину. Наприклад 1/15 = 0,0666666666 .... тому що 3 (15 = 3 * 5) не є коефіцієнтом 10.

Таким чином, все, що може бути представлене в основі 2 точно (k * 1/2 n ), може бути представлене в базі 10 точно.

Крім того, існує питання про те, скільки цифр / бітів ви використовуєте для представлення числа. Існує кілька цифр, які можуть бути точно представлені в якійсь базі, але для цього потрібно більше, ніж деяка кількість цифр / біт.


У двійковій формі число 1/10, яке зручно 0,1 в десятковій частині, не може бути представлене як число, яке може бути представлене фіксованою кількістю бітів у двійковій формі. Натомість число 0,00011001100110011 ... 2 (частина 0011 повторюється назавжди).

Давайте подивимося на число 1 2 /1010 2 трохи ближче.

          ____                  
       0,00011                  
     + ---------                 
1010 | 1.00000                  
       0                        
       -                       
       1 0                      
         0                      
       ----                     
       1 00 --------- +          
          0 |          
       ----- |          
       1 000 |          
           0 |          
       ------ | повторення
       1 0000 | блок    
         1010 |          
       ------ |          
          1100 |          
          1010 |          
          ---- |          
            100 ---- +          

Це точно той самий тип речі, який ви отримуєте, коли намагаєтесь зробити довгий поділ на 1/3.

1/10, коли фактичний коефіцієнт дорівнює 1 / (2 1 * 5 1 ). Для бази 10 (або будь-якого кратного 10) це число закінчується і називається регулярним числом . Десяткове розширення, яке повторюється, відоме як десяткове число, що повторюється , і ті числа, які тривають вічно без повторення, є нераціональними числами.

Математика за цим поглиблюється в малі теореми Ферма ... і як тільки ви починаєте говорити Ферма чи теорема, це стає Math.SE питання .

Чи є номери, які не можуть бути представлені в базі 10, але можуть бути представлені у базі 2?

Відповідь - «ні».

Отже, на цьому етапі всім нам повинно бути зрозуміло, що кожне бінарне розширення з фіксованою довжиною раціонального числа може бути представлене як десяткове розширення з фіксованою довжиною.


Давайте більш уважно подивимось на десятковий знак у C #, який веде нас до десяткової плаваючої точки в .NET і дано автору, я прийму це так, як це працює.

Десятковий тип має ті ж компоненти, що і будь-який інший номер з плаваючою комою: мантіса, експонент та знак. Як завжди, знак - це лише один біт, але є 96 біт мантіси і 5 біт експонента. Однак не всі комбінації експонентів є дійсними. Працюють лише значення 0-28, і вони фактично всі негативні: числове значення є . Це означає, що максимальні та мінімальні значення типу становлять +/- (2 96 -1), а найменше ненульове число за абсолютною величиною - 10 -28 .sign * mantissa / 10exponent

Я одразу зазначу, що через цю реалізацію є номери у doubleтипі, які неможливо представити, decimal- ті, що виходять за межі діапазону. Double.Epsilonце те, 4.94065645841247e-324що не може бути представлене в decimal, а може в а double.

Однак в межах діапазону, який може представляти десятковий, він має більше бітів точності, ніж інші натурні типи, і може представляти їх без помилок.

Навколо плавають деякі інші типи. У C # є BigInteger, який може представляти довільно велике ціле число. Там немає ніякого еквівалента в Java BigDecimal (який може представляти числа з десятковими цифрами до 2 32 цифр довгих - що є значним діапазон) точно . Однак, якщо ви трохи розім’єтеся, ви можете знайти реалізовані вручну реалізації.

Є деякі мови, які також мають раціональний тип даних, який дозволяє точно представляти раціональні дані (так що 1/3 - це фактично 1/3).


Спеціально для C # та вибору float або раціонального, я відкладу до Jon Skeet від плаваючої пінти Decimal у .NET :

Більшість бізнес-додатків, ймовірно, повинні використовувати десятковий, а не плаваючий чи подвійний. Моє правило полягає в тому, що техногенні значення, такі як валюта, як правило, краще представлені десятковою плаваючою комою: наприклад, рівно 1,25 долара цілком розумно. Для значень природного світу, таких як довжини та ваги, бінарні типи з плаваючою комою мають більше сенсу. Незважаючи на те, що існує теоретичне «рівно 1,25 метра», це ніколи не відбудеться в реальності: ви, звичайно, ніколи не зможете виміряти точну довжину, і вони навряд чи існуватимуть на атомному рівні. Ми звикли, що там задіяна певна толерантність.


+1 для чіткого і стислого математичного пояснення. І щоб відповісти на більш загальну версію питання, поставленого в заголовку, приклад числа, який не можна представити в базі 10, становить 1/3.
Doval

@Doval Я підозрюю, що в моїх міркуваннях чи поясненнях є якийсь збій, що більш орієнтована на математику людина може вказати ... але я думаю, що я на вірному шляху, якщо це так.

"Відносно просто" в цьому випадку просто означає "не фактор", правда? Чи є якісь більш глибокі математичні стосунки, які я пропускаю?
Патрік М

1
Ах, так як я розумію, n = 15і b = 10НЕ взаємно прості ( «не поділяють ніяких загальних позитивних факторів (дільник) , за винятком 1») , тому що вони мають 5 в якості фактора. Ключовим є те, що не всі чинники 15 (5 і 3) також не є коефіцієнтами 10. (Окрім того: чи є слово для позначення чисел, які мають чи не поділяють всі загальні чинники?) Я думаю, що це акуратно загорнутий у ваше k, n, mрівняння, але щоб справді обернути голову навколо нього, мені потрібно було б побачити 3d сюжет. Незалежно від вас, заслужений +1.
Патрік М

1
@PatrickM: "Убік: чи є слово для позначення чисел, які роблять чи не поділяють всі загальні чинники?": Будь-яке ціле число є фактором самої себе, тому якщо всі чинники m є факторами n , то тривіально випливає, що m - коефіцієнт n . Один термін для цього, як ви чітко знаєте, є фактором . Інший - дільник .
ruakh

6

Як тільки ви виходите за межі прийнятних значень, відповідь - так. Однак, майже все, що знаходиться в межах асортименту, матиме представництво. C # Десяткове посилання Хоча це не зазначено в специфікації, ірраціональні числа не можуть бути точно представлені (наприклад, e 1 , pi, квадратний корінь 2 і т.д.).

Десяткове ключове слово позначає 128-бітний тип даних. Порівняно з типами з плаваючою комою, десятковий тип має більшу точність та менший діапазон, що робить його придатним для фінансових та грошових розрахунків. Приблизний діапазон та точність для десяткового типу наведені в наступній таблиці.

Точність: 28-29 значущих цифр

1 Дякую MichaelT, що нагадав мені про інше ірраціональне число.


2
@Magus розглянемо ірраціональне число e(2,71 ...). Природний лог - ln (x) - це база журналу e. Таким чином, ірраціональні підстави існують і є корисними. Я не впевнений у конкретній корисності базового пі, але це не означає, що він десь не використовується.

6
@Max ви все більше і більше відхиляєтесь від математичних питань. Ви можете виявити, якщо число нераціональне в базі 10, чи нераціональне воно в інших базах? бути корисним читанням і відправною точкою для питань з більшої теорії чисел.

2
1/3 не є нераціональним.
Адам Цукерман

2
ОП запитала про базу 10 (десять). Створення системи чисел базою чого-небудь дозволить вам виразити що-небудь як 10. Виходячи зі статті Вікіпедії , використання ірраціонального числа як бази не робить його раціональним. Раціональні числа можуть бути виражені цілими числами як для чисельника, так і для знаменника, повторюючи числа в десятковій або скінченного закінчення чисел у десятковій частині.
Адам Цукерман

5
@FrustratedWithFormsDesigner Ірраціональність не має нічого спільного з базами. Ну, це завищення, але саме ірраціональність має значення для представлення числа в різних базах (наприклад, чи має він нескінченні цифри, що не повторюються), а не навпаки. Прочитайте питання math.se, пов’язане з вище: math.stackexchange.com/questions/625473/…

1

Тип типу з плаваючою комою-два може точно відображати багато значень, яких тип базової десяти одного розміру не міг. Будь-яке значення, яке було б точно представлене типом базового типу 2 певного розміру, було б точно представним для достатнього розміру базового десятка. Необхідний розмір для чисто базового типу десять для представлення всіх значень двійкового числа з плаваючою комою залежав би від діапазону експонентів бінарного типу; сотні біт за floatабо тисячі за double.

Зважаючи на це, Decimalтип досить великий, що можна було б використовувати його як "універсальний" тип, здатний утримувати значення будь-якого іншого числового примітиву та надавати додаткові додаткові функції (якщо нічого іншого, використовуйте один біт щоб вказати, чи є збережене значення результатом перетворення a double, і якщо цей біт встановлений, використовуйте 64 біт для утримання відповідного значення). Однак Microsoft вирішила цього не робити. В результаті конверсія а doubleв Decimalне вдасться повністю отримати великі значення, призведе до округлення малих значень до найближчого 1E-28. Далі, навіть у межах динамічного діапазонуdecimal, метод перетворення не буде "зворотним". Наприклад, оцінюючи 1,0 / 3,0 як подвійний, вийде 0,3333333333333333148, але перетворення його в десятковий дасть 0,333333333333333m, а перетворення, що повернеться в подвійне, дасть 0,3333333333333329818.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.