Имя: Пароль:
1C
1С v8
Есть ли в 1с нормальный способ записать число обыкновенной дробью (числ/знам)?
0 cube033
 
21.01.15
06:22
8.3 Управляемое приложение.
Понятно, что можно разобрать число в строку. А потом, при необходимости собрать обратно. Но может кто находил стандартный способ?
1 Рэйв
 
21.01.15
06:23
5/100
чем не устраивает?
2 igoza
 
21.01.15
06:46
Формат("ЧРД=/")
3 igoza
 
21.01.15
06:47
"Текст" -> "Конструктор форматной строки..."
http://programmist1c.ru/st_programming/format-funkcija-formatirovanija-znachenij.html
4 Ненавижу 1С
 
гуру
21.01.15
06:50
А мне кажется, что проблема больше хранения и преобразования в арифметики 1/2+1/3=5/6
5 cube033
 
21.01.15
07:10
(1) чем меня не устраивает конкретно, когда люди делят 5 на 100?
Чтобы было понятно: задача превратить при выводе в отчет "19,2" в "19 1/5". Хоть и криво как-то выглядит, ну или на худой конец 96/5
(2) Получится "19/2"
(3) Только там нет ответа
(4) Если есть алгоритм перевода в дробь, то можно слогаемые поделить как есть, а сумму снова перевести в дробь.Точность конечно потеряется. Но мы хоть как теряем точность при выводе данных пользователю, даже в десятичных дробях(округляем).

Алгоритм я составил. Но может есть таки штатный функционал.
6 sda553
 
21.01.15
07:12
Структура[числитель]=2;
Структура[знаменатель]=5;
7 ifso
 
21.01.15
07:21
(5)
> можно слогаемые поделить как есть
о5 получатся десятичные
или в чем фишка?
8 Asmody
 
21.01.15
07:21
(6) и реализовать арифметику
9 cube033
 
21.01.15
07:23
(6)(8) Не понял идеи. Вот у меня есть чило 19.2, которое мне нужно вывести в отчет как правильную обыкновенную дробь.
И тут:
"Структура[числитель]=2;
Структура[знаменатель]=5; и реализовать арифметику"
10 Asmody
 
21.01.15
07:27
(9) напиши функцию, которая будет для числа возвращать Структура(Целое, Числитель, Знаменатель)
11 cube033
 
21.01.15
07:36
(7) 1/2+1/3=5/6
"> можно слогаемые поделить как есть"
0,5 + 0.33(потеря точности) = 0,83
"а сумму снова перевести в дробь"
83/100 (выразительность числа будет зависеть от округления(в ущерб точности). 0,5+0,3 = 0,8 = 8/10 = 4/5)
Это ответ на "проблема больше хранения и преобразования в арифметики" - вот в чем фишка.
Ахранение меня пока не сильно заботит, так как это формат вывода данных в отчет.

(10) речь идет о выводе через СКД кстати.
Алгоритм есть: Числитель = Дробная часть исходного числа, знаменатель = 1. Умножаем числитель и знаменатель на 10, пока не избавимся от дробной части числителя. Дальше пробуем делить числитель и знаменатель на "индекс от 2 до Числитель цикл" и так пока делится. Но в СКД это не очень удобно.
12 Лодырь
 
21.01.15
07:45
(11) А с какой точностью вы хотите вычислять дроби?
13 Лодырь
 
21.01.15
07:46
Или например, захочет у вас 1С в отчете вывести иррациональное число, что будете делать?
14 IUnknown
 
21.01.15
07:48
(11)как-то через анус ты дробь переводишь ... находишь наибольший кратный делитель и имеешь счастье
15 ifso
 
21.01.15
07:55
(11) угу, идея понятна
но, если в рассмотренном примере в обоих случаях округлять с одинаковой точностью, то и разница нивелируется, не ?
16 Asmody
 
21.01.15
07:56
(13) Не захочет. На 1С реализовать иррациональное число невозможно.
17 Лодырь
 
21.01.15
08:01
(16) Ок, выведет ему ктонибудь тридцатизначное число деленое на тридцатизначное. что он захочет показать? явно не то что надо. а захочет чтонибудь в стиле 45/100 или 36/50. Если сделать предположение, что теоретически можно не полениться и построить вычисляемое поле по попаданию в интервал.
18 IUnknown
 
21.01.15
08:04
0.333


(16)кстати а как сейчас просить создать персональную ветку и создают их или нет?
19 IUnknown
 
21.01.15
08:04
(17)чего?
20 Лодырь
 
21.01.15
08:05
(19) того.
21 IUnknown
 
21.01.15
08:06
(20)"Если сделать предположение, что теоретически можно не полениться и построить вычисляемое поле по попаданию в интервал" вот под этим, что ты имел ввиду?
22 Rebelx
 
21.01.15
08:07
(0) задача элементарная
целая часть - вроде трудностей нет
дробная -
для числителя и знаменателя дробной части находим наибольший общий делитель и делим

все
23 Лодырь
 
21.01.15
08:09
(22) Подразумевалось, что мы строим разбиение интервала (0;1) на полуинтервалы (х;y] каждому которому ставим в соответствие дробь. И используем это в СКД при выводе.
24 Лодырь
 
21.01.15
08:10
тьфу. (23) к (21) а не (22)
25 IUnknown
 
21.01.15
08:11
(23)зачем?
26 Ненавижу 1С
 
гуру
21.01.15
08:12
(13) с иррациональными вообще засада в компьютерах
и с человекопредставлением их тоже
27 Лодырь
 
21.01.15
08:16
(25) это надо спрашивать у топикстартера. это ему надо было такое представление.
28 VladZ
 
21.01.15
08:17
(0) К чему такие извращения?
29 VladZ
 
21.01.15
08:20
По-хорошему, нужно вводить новый тип данных. И писать под него "арифметику". Но таких возможностей в 1С нет. Можно выпендриться через Структуру.

Таким же способом можно реализовать комплексные числа.
Но не понятно, зачем это нужно.
30 VladZ
 
21.01.15
08:21
(4)  Да и это все решаемо.
31 Ненавижу 1С
 
гуру
21.01.15
08:25
мне кажется у автора все проще
есть число фиксированной точности, например 3 знака после запятой: 1.235
и ему его надо представлять в виде 1235/1000
то есть:
Формат(Ч,"ЧС=-3; ЧГ=0")+"/1000"
как прописать только в функции формат я не понял
32 IUnknown
 
21.01.15
08:25
(239)ему надо из 0.45 сделать 1/3 ... непонятно, для чего там какие-то графики строить
33 IUnknown
 
21.01.15
08:25
(31)формат ему не подходит, он говорил ...
34 IUnknown
 
21.01.15
08:26
надо упростить дробь
35 VladZ
 
21.01.15
08:27
(5)  Нужно разработать функцию перевода десятичной дроби в обыкновенную. Дерзай! :)
36 cube033
 
21.01.15
08:53
(33) формат подходит. Просто нужного формата не нашел
37 IUnknown
 
21.01.15
09:04
то есть

0.34565656756 преобразовать в 34565656756/100000000000 тебя вполне устраивает?
38 cube033
 
21.01.15
09:11
(31) идея интересная. Более того задачи свелась к разрядности 1/10. Тогда Формат("ЧРД= ")+"/10". Но далее это текстовое значение не сможет правильно вычисляться в группировках. Да и на практике пока не понятно как в СКД выполнять такого рода конкатенацию.
(37)В моем случае 0.34565656756 будет 3/10 и да - это достаточно. Но 0.35465656756 будет 4/10, а этого будет не достаточно.
39 cube033
 
21.01.15
09:18
"формат подходит. Просто нужного формата не нашел" - Я имею ввиду - идеальным решением было бы нахождение формата при котором 1С делала бы работу за нас.Типа Формат(2,345,"СуперМегаИдеальныйФормат=2") = 2 17/50
40 cube033
 
21.01.15
09:40
41 НЕА123
 
21.01.15
09:54
Стр = СтрЗаменить(Формат(а,"ЧРД=.; ЧН=; ЧГ=0"),Символы.ПС);
Рез = Формат(ПолучитьСТроку(Стр,1),"ЧН=; ЧГ=0");
Если СтрЧислоСтрок(Стр)=2 Тогда
Р
42 НЕА123
 
21.01.15
09:58
все не читал

Стр = СтрЗаменить(Формат(а,"ЧРД=.; ЧН=; ЧГ=0"),".",Символы.ПС);
Рез = Формат(ПолучитьСТроку(Стр,1),"ЧН=; ЧГ=0");
Если СтрЧислоСтрок(Стр)=2 Тогда
   Рез = Рез+" "+Формат(ПолучитьСТроку(Стр,2),"ЧН=") + "/1" +
Лев("0000000000000000000000",СтрДлина(ПолучитьСТроку(Стр,2));
КонецЕсли;
43 IUnknown
 
21.01.15
09:59
(40)там и решения есть)
44 НЕА123
 
21.01.15
10:05
(42)+
*
ПолучитьСтроку = СтрПолучитьСтроку

обратно

стр = СтрЗаменить(Рез," ", Символы.ПС);
Число = Вычислить(СтрПолучитьСТроку(Стр,1) + ?(СтрЧислоСтрок(Стр)=2, "+"+СтрПолучитьСТроку(Стр,2),""))
45 cube033
 
21.01.15
10:32
(43) Да такие решения не сложно придумать. Там задача более математическая что ли. С одной стороны мой пример проще: мне не нужно преобразовывать число обратно. Мне не нужны приближения и отклонения. С другой стороны у меня есть серьезное осложнение, которое отбривает предложеннные решения - СКД.
По сути можно выделить 5 стадий формирования значения в скд
1. Получение набора данных
2. Вычисляемые поля
3. Ресурсы
4. Настройки (Условное оформление)
5. Макет (формат, шаблон)

Поэтому я и спрашивал - нет ли формата нужного. Теперь понимаю что нет.
Я бы уже готов был в шаблоне макета приписать "/10", но вопрос в том, что не всегда значения будут дробными или вообще заполнеными.
В условном оформлении можно задать текст, но вроде нельзя его приплюсовать.
46 cube033
 
21.01.15
11:14
Самый верный путь, как мне кажется - копать в сторону ресурсов. Допустим вот такая формула приписывает "/10" всем ячейкам, но игнорирует формат.

Выбор когда Сумма(Количество) = 0 Тогда 0 Иначе Выразить(Формат(Сумма(Индекс)/Сумма(Количество),"ЧДЦ=1; ЧРД=; ЧН=0; ЧГ="), "Строка") + "/10" Конец
47 quest
 
21.01.15
11:23
sicp первая или вторая глава это обсуждается
48 braslavets
 
21.01.15
11:27
(0) Ну, если точность ограничить - завести рег.сведений, измерение - дробная часть, ресурс - строковое представление в виде "а/б". Один раз заполнить, а дальше просто выцеплять из него.
49 ifso
 
21.01.15
11:41
может быть все-таки стОит изначально определиться с требуемой точностью и спокойно юзать "классику", не ?
50 cube033
 
21.01.15
11:47
(47) 1.2.5. Нахождение наибольшего общего делителя
По определению, наибольший общий делитель (НОД) двух целых чисел a и b — это
наибольшее целое число, на которое и a, и b делятся без остатка. Например, НОД 16 и 28
равен 4. В главе 2, когда мы будем исследовать реализацию арифметики на рациональных
числах, нам потребуется вычислять НОДы, чтобы сокращать дроби. (Чтобы сократить
дробь, нужно поделить ее числитель и знаменатель на их НОД. Например, 16/28 сокра-
щается до 4/7.) Один из способов найти НОД двух чисел состоит в том, чтобы разбить
каждое из них на простые множители и найти среди них общие, однако существует
знаменитый и значительно более эффективный алгоритм.
Этот алгоритм основан на том, что если r есть остаток от деления a на b, то общие
делители a и b в точности те же, что и общие делители b и r. Таким образом, можно
воспользоваться уравнением
НОД(a, b) = НОД(b, r)
чтобы последовательно свести задачу нахождения НОД к задаче нахождения НОД все
41Это упражнение нам предложил Джо Стойна основе примера из Kaldewaij 1990.1.2. Процедуры и порождаемые ими процессы 63
меньших и меньших пар целых чисел. Например,
НОД(206, 40) = НОД(40, 6)
= НОД(6, 4)
= НОД(4, 2)
= НОД(2, 0)
= 2
сводит НОД(206, 40) к НОД(2, 0), что равняется двум. Можно показать, что если на-
чать с произвольных двух целых чисел и производить последовательные редукции, в
конце концов всегда получится пара, где вторым элементом будет 0. Этот способ нахож-
дения НОД известен как алгоритм Евклида (Euclid’s Algorithm)

Интересно, но всё не то. Надо 1С и СКД, а не математику)
51 cube033
 
21.01.15
11:50
(48) Есть извращения и попроще Выбор когда Число%1 = 0.1 Тогда 1/10 когда Число%1 = 0.2 Тогда 1/5 .....
52 cube033
 
21.01.15
11:50
(49) Определился! Точность 1!!! Что за классика??!
53 cube033
 
21.01.15
13:10
Ап. Нет мастеров СКД?
54 ifso
 
21.01.15
15:00
(52) "классика" - десятичные  )
55 mooo
 
21.01.15
15:14
(53) В общем модуле реализовать функцию "ПредставитьЧислоДробью()", в схеме у поля задать выражение представления.
56 cube033
 
22.01.15
05:20
(54) Я вот тоже боюсь, с точностью 1 знак после запятой - обыкновенные дроби читаемость отчета никак не повысят.
(55) Тема не распространенная, но интересная. Говорят только в ресурсах можно пользоваться.
57 cube033
 
22.01.15
07:27
(55) Спасибо. В итоге вопрос РЕШЕН. Кто будет искать решение - Вот оно.
1.Создаем (или используем гтовый) общий модуль со свойствами: глобальный, сервер, внешнее соединение, вызов сервер.
2.Создаём Экспортную функцию. (в моем случае перевода в дробь нет, но это самое простое. Куча способов описана в этой теме и в теме по ссылке (40)).

Функция ПолучитьДробьСтрокой(ЧислоВходящее) Экспорт
    Если ТипЗнч(ЧислоВходящее) = Тип("Null") Тогда
        Возврат Null;
    КонецЕсли;
    ДробнаяЧасть = ЧислоВходящее - Цел(ЧислоВходящее);
    Если  ДробнаяЧасть = 0 тогда
        Возврат Строка(ЧислоВходящее);
    КонецЕсли;
    ДробнаяЧасть = Окр(ДробнаяЧасть,1);
    ЦелаяЧастьСтрока = ?(Цел(ЧислоВходящее) = 0,"",Строка(Цел(ЧислоВходящее)));
    Если ДробнаяЧасть = 0 Тогда
        Возврат ЦелаяЧастьСтрока;
    ИначеЕсли ДробнаяЧасть = 0.1 Тогда
        Возврат ЦелаяЧастьСтрока + " 1/10";
    .........................................
    ИначеЕсли ДробнаяЧасть = 0.9 Тогда
        Возврат ЦелаяЧастьСтрока + " 9/10";
    ИначеЕсли ДробнаяЧасть = 1 Тогда
        Возврат Строка(Цел(ЧислоВходящее+1));
    КонецЕсли;
КонецФункции

3. В Схеме компоновки данных, на вкладке ресурсы берем выражение (например: Сумма(ХорошиеЧисла)/Сумма(ПлохиеЧисла)) и передаем его параметров, вызывая свою функцию "ПолучитьДробьСтрокой(Сумма(ХорошиеЧисла)/Сумма(ПлохиеЧисла))"
Работает в файловом и серверном режимах.
58 VladZ
 
22.01.15
08:00
ИначеЕсли ДробнаяЧасть = 0.1 Тогда
        Возврат ЦелаяЧастьСтрока + " 1/10";
    .........................................
    ИначеЕсли ДробнаяЧасть = 0.9 Тогда
        Возврат ЦелаяЧастьСтрока + " 9/10";
    ИначеЕсли ДробнаяЧасть = 1 Тогда

ЫЫЫЫ... Эту часть можно было сделать и по-красивее.
Раз у тебя точность 1 знак. Берем этот знак и делаем так:

ПоследнийСимволСтрокой + "/10". И накаких тебе лестниц с "ИначеЕсли" не нужно.

В целом: не нравится мне идея с округлением. Теряется часть инфы.
59 DrZombi
 
гуру
22.01.15
08:02
(57) Шот там не то. Ты если взялси, то пили до конца.
А так, спасибо, но мы как нить обычным двоичным исчислением ограничимси :)
60 cube033
 
22.01.15
08:04
(58) ЫЫЫ Ты же не думаешь, что я пропустил 2/10,3/10 итд))

Если ДробнаяЧасть = 0 Тогда
        Возврат ЦелаяЧастьСтрока;
    ИначеЕсли ДробнаяЧасть = 0.1 Тогда
        Возврат ЦелаяЧастьСтрока + " 1/10";
    ИначеЕсли ДробнаяЧасть = 0.2 Тогда
        Возврат ЦелаяЧастьСтрока + " 1/5";
    ИначеЕсли ДробнаяЧасть = 0.3 Тогда
        Возврат ЦелаяЧастьСтрока + " 3/10";
    ИначеЕсли ДробнаяЧасть = 0.4 Тогда
        Возврат ЦелаяЧастьСтрока + " 2/5";
    ИначеЕсли ДробнаяЧасть = 0.5 Тогда
        Возврат ЦелаяЧастьСтрока + " 1/5";
    ИначеЕсли ДробнаяЧасть = 0.6 Тогда
        Возврат ЦелаяЧастьСтрока + " 3/5";
      ИначеЕсли ДробнаяЧасть = 0.7 Тогда
        Возврат ЦелаяЧастьСтрока + " 7/10";
    ИначеЕсли ДробнаяЧасть = 0.8 Тогда
        Возврат ЦелаяЧастьСтрока + " 4/5";
    ИначеЕсли ДробнаяЧасть = 0.9 Тогда
        Возврат ЦелаяЧастьСтрока + " 9/10";
    ИначеЕсли ДробнаяЧасть = 1 Тогда
        Возврат Строка(Цел(ЧислоВходящее+1));
    КонецЕсли;
61 cube033
 
22.01.15
08:07
(58) Это и есть до конца в каком-то смысле.
Задача была с точностью 1.
Было бы не верным для 10 значений делать сначала цикл нахождения целых чисел, а потом нахождение НОД
62 VladZ
 
22.01.15
08:11
(60)  Я не про то.

ИначеЕсли (Прав(ДробнаяЧасть, 1) = "1")
или (Прав(ДробнаяЧасть, 1) = "3")
или (Прав(ДробнаяЧасть, 1) = "7")
или (Прав(ДробнаяЧасть, 1) = "9")

Возврат ЦелаяЧастьСтрока + " "+Прав(ДробнаяЧасть, 1)+"/10";

Тогда...
63 VladZ
 
22.01.15
08:13
Или в случае, если бы не было всяких  1/5, 3/5 вообще приходим к одной строке.
64 Провинциальный 1сник
 
22.01.15
08:18
Рассмотрим вопрос шире - есть ли языки программирования, где есть тип данных "обыкновенная дробь" и соответственно математические операции над ними с сохранением обыкновенности (с числителем и знаменателем)?
65 ifso
 
22.01.15
08:21
(61) ну, пили уже и составные ^^

зы изучай клинопись - судя по ТЗ, клиенты вот-вот созреют и подтянуца )
66 cube033
 
22.01.15
08:48
(62) Спасибо. увидел свою ошибку 0.2 = 1/5

Если (Прав(ДробнаяЧасть, 1) = "1")
или (Прав(ДробнаяЧасть, 1) = "3")
или (Прав(ДробнаяЧасть, 1) = "7")
или (Прав(ДробнаяЧасть, 1) = "9")
Возврат ЦелаяЧастьСтрока + " "+Прав(ДробнаяЧасть, 1)+"/10";
ИначеЕсли (Прав(ДробнаяЧасть, 1) = "5")
Возврат ЦелаяЧастьСтрока + " 1/2";
Иначе
Возврат ЦелаяЧастьСтрока + " 1/5";

Мне кажется то же самое, только в профиль, но читаемость ниже.
67 cube033
 
22.01.15
08:49
(66) Опять блин... Т.е 0,5 = 1/5 - это ошибка
68 cube033
 
22.01.15
08:52
"В целом: не нравится мне идея с округлением. Теряется часть инфы."
Изначально задача была - округление до целого.
69 VladZ
 
22.01.15
08:55
(66) поставь сначала "извращения", потом все остальное. Читабельность будет лучше.
70 VladZ
 
22.01.15
08:59
как-то так:

ПоследнийСимволДробнойЧасти = Прав(ДробнаяЧасть, 1);

Если (ПоследнийСимволДробнойЧасти = "5")
Возврат ЦелаяЧастьСтрока + " 1/2";

ИначеЕсли ПоследнийСимволДробнойЧасти = "2"
Возврат ЦелаяЧастьСтрока + " 1/5";

Иначе
Возврат ЦелаяЧастьСтрока + " "+ПоследнийСимволДробнойЧасти + "/10";
КонецЕсли;
Оптимист верит, что мы живем в лучшем из миров. Пессимист боится, что так оно и есть.