Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> формат double при преобразовании в текст, Откуда лишние нули при форматном преобр. 
V
    Опции темы
Mirkes
Дата 3.12.2011, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Проблема примитивная.
Вывожу в окно редактирования число. Приэтом прочитав ряд тем на форуме указываю формат вывода, но получаю не совсем то, что ожидалось.
Текст устанавливаю следующей строкой
Код

        double elas;
        ...
        elast.setText(String.format(Locale.US, "%7.5g", elas));


При значении
Значение    отображение в строке
0.1              0.10000                 как и должно быть
0.01            0.010000               лишний ноль
0.001          0.0010000             два лишних нуля
0.0001        0.00010000           три лишних нуля
0.00001      1.0000e-05            как и должно быть

При этом за нулями нет никаких чудес, типа хвостов не вошедших на экран
Вопрос, откуда дополнительные нули при выводе? И почему их разное количество?


--------------------
Mirkes
PM MAIL   Вверх
nc30
Дата 4.12.2011, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Интересующийся :)
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 24.6.2010
Где: Санкт-Петербург

Репутация: 5
Всего: 8



"%7.5f"

0.10000
0.01000
0.00100
0.00010
0.00001

http://docs.oracle.com/javase/6/docs/api/j...ter.html#syntax
PM MAIL   Вверх
Mirkes
Дата 5.12.2011, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Спасибо за ссылку, но уже читал.
Предложенный формат не годится, поскольку выдает
0.000001 в виде 0.00000 а надо бы 1.е-6. Именно по этой причине я использовал формат g. 
Судя по скорости возникновения ответов я первый с этим столкнулся или это свойство Java и надо с ним просто смириться?


--------------------
Mirkes
PM MAIL   Вверх
math64
Дата 5.12.2011, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



7 знаков не хватает, чтобы вывести в формате e c точностью 5 знаков,
По видимому, 7 игнорируется и заменяется на 10, т.е. фактически вывод идёт в формате 10.5g
PM   Вверх
Mirkes
Дата 5.12.2011, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Если бы было так, то все числа выводились бы в 10 знаков, а выводится по какойто странной схеме, которую я не могу понять.
Я точн знаю что у меня будет не более одной цифры в целых, плюс один символ на точку и пять после запятой. Получаем 7.5. Для g нужно записать e+01 символ до точки, точку и пять символов после запятой - итого 11 символов, Вы это имели в виду?
Поставил 10.5g
результат
0.1             3 пробела   0.10000
0.01           2 пробела   0.010000
0.0001       0 пробелов  0.00010000
0.00001     0 пробелов  1.0000e-05 

Опять ничего не понимаю. Почему возникает более 5 цифр в дробной части?


--------------------
Mirkes
PM MAIL   Вверх
math64
Дата 5.12.2011, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Для формата g, я полагаю, может и ошибаюсь - поищите в документации - вторая цифра число значащих цифр, а не знаков после запятой.
Сначала пробуется формат e, затем проверяется можно ли число представить в формате f меньшим числом знаков.
В 0.00010000 значащие цифры - 10000 - их 5, а 0.000 - не значащие

PM   Вверх
nc30
Дата 5.12.2011, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Интересующийся :)
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 24.6.2010
Где: Санкт-Петербург

Репутация: 5
Всего: 8



Лирика, конечно, но все же.
Цитата(Mirkes @ 5.12.2011,  15:25)
Я точн знаю что у меня будет не более одной цифры в целых, плюс один символ на точку и пять после запятой.

Если вы точно знаете, что вам нужно 5 цифр после запятой, зачем рассматривать вариант
Цитата(Mirkes @ 5.12.2011,  11:28)
0.000001 в виде 0.00000 а надо бы 1.е-6
?

PM MAIL   Вверх
Mirkes
Дата 5.12.2011, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Цитата(math64 @  5.12.2011,  15:42 Найти цитируемый пост)
В 0.00010000 значащие цифры - 10000 - их 5, а 0.000 - не значащие 

Вообще говоря меня учили как раз наоборот, 0.0001 - значащие цифры, а вот хвостовые нули - не значащие.
Цитата(nc30 @  5.12.2011,  18:19 Найти цитируемый пост)
Если вы точно знаете, что вам нужно 5 цифр после запятой, зачем рассматривать вариантЦитата(Mirkes @ 5.12.2011,  11:28)0.000001 в виде 0.00000 а надо бы 1.е-6? 

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

Провел ряд тестов. Стал понимать еще меньше.
вот программа
Код

import java.io.*;
import java.util.Locale;

class MyClass

public static void main(String argv[])
{
 double x=0.1;
 for (int i=1;i<10;i++){
   System.out.println(String.format(Locale.US, "%12.5g", x));
   x/=10;
 }

}

Вот результаты при разных форматах
"%7.5g"
0.10000
0.010000
0.0010000
0.00010000
1.0000e-05
1.0000e-06
1.0000e-07
1.0000e-08
1.0000e-09

"%10.5g"
   0.10000
  0.010000
 0.0010000
0.00010000
1.0000e-05
1.0000e-06
1.0000e-07
1.0000e-08
1.0000e-09

"%12.5g"
     0.10000
    0.010000
   0.0010000
  0.00010000
  1.0000e-05
  1.0000e-06
  1.0000e-07
  1.0000e-08
  1.0000e-09

Пробелы вставлены java, а не мной!
Кто-нибудь может что-нибудь внятное сказать о работе формата g?
Форматы f и е работают корректно и предсказуемо, но в моем случае не совсем подходят.
А в чем дело с форматом g?
Еще раз перечитал документацию и не нашел ответа. Подскажите, кто знает.


--------------------
Mirkes
PM MAIL   Вверх
jk1
Дата 6.12.2011, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 40
Всего: 75



Цитата

Пробелы вставлены java, а не мной!


Об этом как раз в документации написано. Дело в том, что выравнивание по умолчанию происходит по правому краю. Для выравнивания по левому надо использовать флаг "-"

Код

"%-12.5g"
0.10000     
0.010000    
0.0010000   
0.00010000  
1.0000e-05  
1.0000e-06  
1.0000e-07  
1.0000e-08  
1.0000e-09 



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Nikolja
Дата 6.12.2011, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 24.2.2009
Где: Черкассы

Репутация: нет
Всего: -1



Вопрос любопытный у вас, Mirkes !

"Откуда есть пошёл" smile форматированый вывод? Из языка Си, функция printf() из stdio.h
Вот я, интереса ради, и обратился к основам, чтобы разобраться. А то уже самому интересно стало! smile

Вот, допустим, такая программка на Си.
Код

#include <stdio.h>

double a, b, c, d, e;

int main () {

   a = 0.1;
   b = 0.01;
   c = 0.001;
   d = 0.0001;
   e = 0.00001;

   printf ("a = %7.5g\n", a);
   printf ("b = %7.5g\n", b);
   printf ("c = %7.5g\n", c);
   printf ("d = %7.5g\n", d);
   printf ("e = %7.5g\n", e);

   getch();
   return 0;
}


Что она выдаёт? Вот что. Вот так.

   a =     0.1
   b =    0.01
   c =   0.001
   d =  0.0001
   e =   1e-05
   

Для верности откомпилировал эту програмку разными компиляторами. 
Совершенно новым Dev C++ 5.0.0.8 от 20 ноября 2011 года. 
И старой доброй классикой -- Turbo C++ 3.0 (Borland) 20-летней давности. Результат выводится один и тот же!

Написал аналогичную программу в Java (1.6.0_12). Выдаёт то же, что и у вас.
Значит есть разница в использовании "g" в языках Си и Java. В чём? А вот в чём.

Напишем аналогичную программку на Си. Только вместо числа 0.1 возьмём число, где побольше значащих разрядов: 0.12345

Код

#include <stdio.h>

double a, b, c, d, e;

int main () {

   a = 0.12345;
   b = 0.012345;
   c = 0.0012345;
   d = 0.00012345;
   e = 0.000012345;

   printf ("a = %7.5g\n", a);
   printf ("b = %7.5g\n", b);
   printf ("c = %7.5g\n", c);
   printf ("d = %7.5g\n", d);
   printf ("e = %7.5g\n", e);

   getch();
   return 0;
}


Она выводит

   a = 0.12345
   b = 0.012345
   c = 0.0012345
   d = 0.00012345
   e = 1.2345e-05

   
Видите аналогию с вашей программой? 

Если выводить число в формате "g" (а не "f"), то значение после точки означает кол-во значащих разрядов (а не кол-во цифр в дроби после запятой/точки, как в "f").
Например %7.5g
Значит 5 значащих разрядов. Signficant digits по англ.

И ВОТ ЧТО ВАЖНО! 5, в записи выше, имеет БОЛЬШИЙ ПРИОРИТЕТ, чем 7 (т.е. кол-во знакомест).
PM MAIL   Вверх
Mirkes
Дата 6.12.2011, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Бог с ними с пробелами, меня нули лишние интересуют. Похоже формат g означает, что сначала формируется формат e, а далее он сдвигается на указанное число разрядов, но не более чем на 4 вправо. Дл сдвига влево ограничение другое, не четыре разряда. При этом хвостовые нули оставляются. Это несколько странный вариант такого формата. Ради интереса проверил в delphi (то, чо было под рукой)

Delphi
Код

uses
  SysUtils;

Var
  X: double;
  I: Integer;
begin
  X:=0.1;
  For I := 1 To 9 Do
    Begin
      WriteLn(FloatToStrF(X,ffGeneral,12,5));
      X:=X/10;
    End;
    ReadLn;
end.

Результат
0.1
0.01
0.001
0.0001
1E-5
1E-6
1E-7
1E-8
1E-9

вполне приемлемо.


--------------------
Mirkes
PM MAIL   Вверх
Nikolja
Дата 6.12.2011, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 24.2.2009
Где: Черкассы

Репутация: нет
Всего: -1



Цитата(Mirkes @ 6.12.2011,  13:15)
меня нули лишние интересуют

В Си в такой записи %7.5g хвостовые нули (англ. trailing zeros) НЕ ВЫВОДЯТСЯ.
А в Яве ВЫВОДЯТСЯ ! Вот в чём разница!

Т.е. для языка Java число 0.01, к примеру, будет выводиться с ЕЩЁ 4-МЯ ЦИФРАМИ после единички. 0.010000. 

Короче говоря, Яве всё равно (в отличие от Си), что 0.01, что 0.012345. ВСЁ, что после первой значащей цифры (здесь единица) будет выводиться на экран. Даже нули.

Вот я жирным выделил ТО, что Java считает обязательным для вывода (при %7.5g). ПЯТЬ СИМВОЛОВ.

0.010000
0.012345

0.0010000
0.00010000

А 7 знакомест -- это второстепенно. Получится -- выведет, не получится -- значит нет. smile

Это сообщение отредактировал(а) Nikolja - 6.12.2011, 13:38
PM MAIL   Вверх
Nikolja
Дата 6.12.2011, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 24.2.2009
Где: Черкассы

Репутация: нет
Всего: -1



Mirkes, я понятно объяснил?

Добавлено через 8 минут и 44 секунды
Код

   System.out.println(String.format(Locale.US, "%12.5g", x));
А вот это можно записать проще, если угодно.
В Java тоже появилась (с 5-ой версии Java) функция, пардон, метод printf().

Например, та программа на Си, что выше, на Java может выглядеть ТАК.
Код

class Vingrad {
  public static void main (String args[]) {

    double a, b, c, d, e;

    a = 0.1;
    b = 0.01;
    c = 0.001;
    d = 0.0001;
    e = 0.00001;

    System.out.printf("a = %7.5g\n", a);
    System.out.printf("b = %7.5g\n", b);
    System.out.printf("c = %7.5g\n", c);
    System.out.printf("d = %7.5g\n", d);
    System.out.printf("e = %7.5g\n", e);

  }
}

PM MAIL   Вверх
Mirkes
Дата 6.12.2011, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Цитата(Nikolja @  6.12.2011,  13:05 Найти цитируемый пост)
"Откуда есть пошёл"  форматированый вывод? Из языка Си, функция printf() из stdio.h

Сожалею, но вы ошиблись лет на 30. Первый форматный вывод был в FORTRAN, далее в PL1, ALGOL, ADA и уже много позже в С. Это просто историческая справка. Кстати и в  FORTRAN и в PL1 вывод осуществлялся так же, как в моем примере на Pascal или в Вашем на C.

Вы подтвердили мои подозрения насчет способа вывода в Java. Спасибо, буду знать, что хвостовые нули есть неотъемлемле свойство формата g.


--------------------
Mirkes
PM MAIL   Вверх
Nikolja
Дата 6.12.2011, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 24.2.2009
Где: Черкассы

Репутация: нет
Всего: -1



Цитата(Mirkes @ 6.12.2011,  17:46)
Цитата(Nikolja @  6.12.2011,  13:05 Найти цитируемый пост)
"Откуда есть пошёл"  форматированый вывод? Из языка Си, функция printf() из stdio.h

Сожалею, но вы ошиблись лет на 30. Первый форматный вывод был в FORTRAN, далее в PL1, ALGOL, ADA и уже много позже в С. Это просто историческая справка. 

Вообще-то я имел в виду языки с Си-подобным синтаксисом. Наверное, не очень чётко выразился.
Я хотел сказать "ТАКОЙ форматированный вывод" (или "форматный" - встречал и такой, и такой перевод.). С такими обозначениями f, g, d, o и т.п.

Возможно, вы неточны в своей датировке. Язык Си появился в 1972 г. Минус 30 лет -- это что же получается, 1942-ой, что ли? smile

Фортран появился в 1958 г. приблизительно. (т.е. не 30 лет, а в 2 раза меньше; лет 14 разница). 
PL/1 в середине 60-х.
smile Ада -- и вовсе позже, чем Си. В конце 70-х.

Цитата
Кстати и в  FORTRAN и в PL1 вывод осуществлялся так же, как в моем примере на Pascal или в Вашем на C.
 Тут задумался над смыслом сказанного... Синтаксис то разный в этих языках? Имеется в виду без хвостовых нулей, наверное?

smile Вот поди пойми -- кому советуешь! В соседней теме некто Voron91 спрашивает, что такое printf() и что там символы % и d означают (ответить, что ли?) -- совсем новичок; а здесь человек рассуждает о таких языках, которым лет больше, чем большинству присутствующих на форуме. Уже одно, что названия такие знает, заслуживает уважения smile . Respect!

Добавлено @ 20:53
Цитата(Mirkes @ 6.12.2011,  17:46)
Вы подтвердили мои подозрения насчет способа вывода в Java. Спасибо, буду знать, что хвостовые нули есть неотъемлемле свойство формата g.

Во всяком случае при таком написании g.

В языке Си существует возможность и выводить и не выводить эти самые хвостовые нули в формате g. Можно сделать, чтобы вывод в Си получался точно такой же, как в вашей программе на Java.
Для этого ставится флаг #. Если, например, в ту программу, что выше была, поставить.
Код

   a = 0.1;
   b = 0.01;
   c = 0.001;
   d = 0.0001;
   e = 0.00001;

   printf ("a = %#7.5g\n", a);
   printf ("b = %#7.5g\n", b);
   printf ("c = %#7.5g\n", c);
   printf ("d = %#7.5g\n", d);
   printf ("e = %#7.5g\n", e);

Возможно в языке Java тоже существует подобная возможность, но я честно и скромно скажу, что лично я такого не знаю. Флаг # в Яве не работает в данном случае. Выдаёт ошибку.

Это сообщение отредактировал(а) Nikolja - 6.12.2011, 21:30
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1396 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.