2012-06-05 1 views
3

Предположим, я хочу преобразовать число 0.011124325465476454 в строку в MATLAB.Преобразование числа в строку в MATLAB

Если я ударил

mat2str(0.011124325465476454,100)

я 0.011124325465476453, отличающуюся в последней цифре.

Если я ударил num2str(0.011124325465476454,'%5.25f')

Я получаю 0.0111243254654764530000000

, которая дополняется с нежелательными нулями и отличающуюся в последней цифре (3 должно быть 4).

Мне нужен способ преобразования чисел со случайным числом десятичных знаков в соответствие их точной строке (без нулей, без изменения окончательной цифры).

Есть ли способ?

EDIT: Поскольку я не имею в виду информацию о точности, которую предоставляют Amro и nrz, я добавляю дополнительную дополнительную информацию о проблеме. Цифры, которые мне действительно нужно преобразовать, поступают из программы на C++, которая выводит их в txt-файл, и все они имеют тип C++ double. [ПРИМЕЧАНИЕ. Часть, которая вводит числа из файла txt в MATLAB, не кодируется мной, и мне на самом деле не разрешено изменять ее, чтобы сохранить числа в виде строк без преобразования их в числовые значения. У меня есть доступ к «выходному» этому коду, который представляет собой число, которое я хотел бы преобразовать]. До сих пор я не получал номера с более чем 17 десятичными знаками (ПРИМЕЧАНИЕ: следовательно, приведенный выше пример с 18 десятичными знаками не очень показательен).

Теперь, если число имеет 15 цифр, например 0.280783055069002

затем num2str(0.280783055069002,'%5.17f') или mat2str(0.280783055069002,17) возвращает

0.28078305506900197

, который не является точным числом (см последних цифр).

Но если я ударил mat2str(0.280783055069002,15) я

0.280783055069002 который правильно !!!

Возможно, существует миллион способов «кодирования» проблемы (например, создать процедуру, которая выполняет преобразование), но нет способа использовать стандартный встроенный MATLAB для получения желаемых результатов при вводе числа со случайным числом десятичных знаков (но не более 17);

ответ

4

Мой HPF набор инструментов также позволяет работать с произвольной точностью чисел в MATLAB.

В MATLAB, попробуйте следующее:

>> format long g 
>> x = 0.280783054 
x = 
       0.280783054 

Как вы можете видеть, MATLAB записывает его с цифрами вы поставленные. Но как MATLAB действительно «чувствует» это число? Что он хранит внутри страны? Посмотрите, что Sprintf говорит:

>> sprintf('%.60f',x) 
ans = 
0.280783053999999976380053112734458409249782562255859375000000 

И это то, что видит HPF, когда он пытается извлечь это число из двойной:

>> hpf(x,60) 
ans = 
0.280783053999999976380053112734458409249782562255859375000000 

То есть, почти все десятичные числа не представима точно арифметика с плавающей точкой как двойная. (0,5 или 0,375 являются исключениями из этого правила по очевидным причинам.)

Однако, если хранить в десятичной форме с 18 цифрами, мы видим, что HPF не нужно было хранить это число как двоичное приближение к десятичной форме ,

x = hpf('0.280783054',[18 0]) 
x = 
0.280783054 

>> x.mantissa 
ans = 
    2 8 0 7 8 3 0 5 4 0 0 0 0 0 0 0 0 0 

Какие цифры не ценят, так это то, что десятичные числа не сохраняются в десятичной форме как двойной. Например, как выглядит 0,1 внутри себя?

>> sprintf('%.60f',0.1) 
ans = 
0.100000000000000005551115123125782702118158340454101562500000 

Как вы видите, matlab не сохраняет его как 0,1. На самом деле, Matlab хранит 0.1 в виде двоичного числа, здесь действует ...

1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + ... 

или, если вы предпочитаете

2^-4 + 2^-5 + 2^-8 + 2^-9 + 2^-12 + 2^13 + 2^-16 + ... 

Представлять 0.1 точно, это заняло бы бесконечно много таких терминов, так как 0.1 повторяющееся число в двоичном формате. MATLAB останавливается на 52 бит. Точно так же, как 2/3 = 0,6666666666 ... как десятичное число, 0,1 хранится только как приближение в виде двойного.

Вот почему ваша проблема действительно полностью связана с точностью и бинарной формой, состоящей из двойника.

В качестве последнего редактирования после чата ...

Дело в том, что MATLAB использует двойной представлять ряд. Таким образом, он будет содержать число до 15 десятичных цифр и сможет вытолкнуть их с правильной настройкой формата.

>> format long g 
>> eps 
ans = 
2.22044604925031e-16 

Так, например ...

>> x = 1.23456789
x = 
      1.23456789

И мы видим, что MATLAB получил это право. Но добавьте еще одну цифру до конца.

>> x = 1.23456789
x = 
      1.23456789

В своей полной красе, смотреть на х, так как MATLAB видит:

>> sprintf('%.60f',x) 
ans = 
1.23456789

Поэтому всегда остерегайтесь последнюю цифру любого числа с плавающей точкой. MATLAB будет пытаться объединить все разумно, но 15 цифр находятся на грани того, где вы в безопасности.

Нужно ли использовать такой инструмент, как HPF или MP, для решения такой проблемы? Нет, если вы признаете ограничения двойника. Однако инструменты, которые предлагают произвольную точность, дают вам возможность быть более гибкими, когда вам это нужно. Например, HPF предлагает использовать и контролировать контрольные цифры в этой области подвала. Если они вам нужны, они там, чтобы сохранить нужные вам цифры от коррупции.

+0

@niels - Но вы просто не можете достичь требуемой точности, не используя инструмент, который позволяет работать с большей точностью. Как много, вам нужно признать, что использование числовой формы с плавающей запятой (которая является тем, что удваивается) всегда будет оставлять эту наименее значимую цифру под угрозой. Другим достоинством такой формы, как HPF, является то, что она десятичная. Таким образом, цифры сохраняются в десятичной форме, а не в двоичной форме. –

+1

@niels - Да, это ПОЛНОСТЬЮ относительно точности и того, как число хранится как двоичное число в двойном. До тех пор, пока вы не поймете, что 0.280783054 НЕ представляется в виде числа с плавающей запятой BINARY точно, вы никогда не сможете решить эту проблему. –

+0

MATLAB сохраняет все числа как двойные по умолчанию, поэтому 52 бинарных бита для мантиссы. Если бы вы использовали сингл для хранения номера, то x = single (0.280783054); вы получите: sprintf ('%. 30f', x) ans = 0.280783057212829589843750000000 –

0

Это потому, что ваш номер превышает точность числового типа double (он дает от 15 до 17 значащих десятичных цифр). В вашем случае он округляется до ближайшего представимого числа, как только будет оцениваться литерал.

Если вам нужна более высокая точность, чем то, что обеспечивают плавающие точки с двойной точностью, хранить номера в строках или использовать библиотеки с произвольной точностью.Например использовать Символическое Toolbox:

sym('0.0111243254654764549999999') 
0

Вы не можете получить ТОЧНУЮ строку, так как номер хранится в двойном типе или даже в длинном двойном типе. Сохраняемое количество будет более тонким, чем число, которое вы даете.

компьютер знает только двоичное число 0 & 1. Вы должны знать, что числа в одном радиусе могут не выражаться одинаково в другом основании. Например, число 1/3, radix 10 дает 0.33333333 ... (Эллипсис (три точки) указывает, что все равно будет больше цифр, вот цифра 3), и она будет усечена до 0,3333333; radix 3 дает 0.10000000, см., не более или менее, точно сумму; radix 2 дает 0.01010101 ..., поэтому он, скорее всего, будет усечен до 0,01010101 на компьютере, это 85/256, менее 1/3 округлением, а в следующий раз, когда вы получите номер, это будет не то же самое, что вы хотите ,

Итак, с самого начала вы должны сохранить число в строке вместо типа float, иначе оно потеряет точность.

Учитывая проблему точности, MATLAB обеспечивает символическое вычисление произвольной точности.