Просто для удовольствия я играл с представлением поплавков, следуя определениям из стандарта C99, и я написал код ниже.
Код печатает двоичное представление поплавков в 3 отдельных группах
SIGN EXPONENT FRACTION
, и после этого он печатает сумму, которая при суммировании с достаточной точностью покажет значение, которое действительно существует в аппаратном обеспечении.
Поэтому, когда вы пишете float x = 999...
компилятор преобразует это число в битовое представление, напечатанное функцией xx
, так что сумма, напечатанная функцией yy
, будет равна заданному числу.
В действительности эта сумма является только приближение. Для числа 999,999,999 компилятор будет вставлять в бит представление float число 1,000,000,000
После кода я присоединяю консольный сеанс, в котором я вычисляю сумму терминов для обеих констант (минус PI и 999999999) который действительно существует в аппаратном обеспечении, вставленном там компилятором.
#include <stdio.h>
#include <limits.h>
void
xx(float *x)
{
unsigned char i = sizeof(*x)*CHAR_BIT-1;
do {
switch (i) {
case 31:
printf("sign:");
break;
case 30:
printf("exponent:");
break;
case 23:
printf("fraction:");
break;
}
char b=(*(unsigned long long*)x&((unsigned long long)1<<i))!=0;
printf("%d ", b);
} while (i--);
printf("\n");
}
void
yy(float a)
{
int sign=!(*(unsigned long long*)&a&((unsigned long long)1<<31));
int fraction = ((1<<23)-1)&(*(int*)&a);
int exponent = (255&((*(int*)&a)>>23))-127;
printf(sign?"positive" " ( 1+":"negative" " ( 1+");
unsigned int i = 1<<22;
unsigned int j = 1;
do {
char b=(fraction&i)!=0;
b&&(printf("1/(%d) %c", 1<<j, (fraction&(i-1))?'+':')' ), 0);
} while (j++, i>>=1);
printf("*2^%d", exponent);
printf("\n");
}
void
main()
{
float x=-3.14;
float y=999999999;
printf("%lu\n", sizeof(x));
xx(&x);
xx(&y);
yy(x);
yy(y);
}
Вот сеанс консоли, в котором я вычисляю реальное значение float, которое существует в аппаратном обеспечении. Я использовал bc
для печати суммы терминов, выводимых основной программой. Можно вставить эту сумму в python repl
или что-то подобное.
-- .../terra1/stub
@ qemacs f.c
-- .../terra1/stub
@ gcc f.c
-- .../terra1/stub
@ ./a.out
sign:1 exponent:1 0 0 0 0 0 0 fraction:0 1 0 0 1 0 0 0 1 1 1 1 0 1 0 1 1 1 0 0 0 0 1 1
sign:0 exponent:1 0 0 1 1 1 0 fraction:0 1 1 0 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 0 1 0 0 0
negative ( 1+1/(2) +1/(16) +1/(256) +1/(512) +1/(1024) +1/(2048) +1/(8192) +1/(32768) +1/(65536) +1/(131072) +1/(4194304) +1/(8388608) )*2^1
positive ( 1+1/(2) +1/(4) +1/(16) +1/(32) +1/(64) +1/(512) +1/(1024) +1/(4096) +1/(16384) +1/(32768) +1/(262144) +1/(1048576) )*2^29
-- .../terra1/stub
@ bc
scale=15
( 1+1/(2) +1/(4) +1/(16) +1/(32) +1/(64) +1/(512) +1/(1024) +1/(4096) +1/(16384) +1/(32768) +1/(262144) +1/(1048576) )*2^29
999999999.999999446351872
Вот и все. Фактически значение 999999999
999999999.999999446351872
Вы также можете проверить с помощью bc
, что -3.14 также возмущено. Не забудьте установить коэффициент scale
в bc
.
Отображаемая сумма - это то, что внутри аппаратного обеспечения. Значение, которое вы получаете, вычисляя его, зависит от установленного вами масштаба. Я установил коэффициент scale
равным 15. Математически, с бесконечной точностью, кажется, что это 1 000 000 000.
В любом случае HashMap не должен появляться в вашей модели UML. HashMap - это всего лишь реализация квалифицированной ассоциации. Вероятно, это даже просто скорость, улучшающая неквалифицированную ассоциацию. Поэтому, если у вас есть класс A с HashMap, вы бы моделировали UML-класс A, UML-класс B и ассоциацию UML от A до B. Вы можете добавить квалификатор в ассоциацию, если он квалифицирован ключом, который не является атрибутом B. Если ваш ключ HashMap является именем B (и B имеет это имя в качестве атрибута), вы просто опустите квалификатор.
Чтобы обозначить реализацию вашей Ассоциации (вы хотите реализовать ее с помощью HashSet), вы можете добавить это как ключевое слово или создать для него стереотип (более сложный).
HashMap - это только один из многих классов Java. И вы можете использовать любой класс java, интерфейс или примитивный тип в диаграмме классов UML 2.0. Любой тип данных в диаграмме классов Java UML 2.0 соответствует некоторому java-классу, интерфейсу или примитиву.
Вы используете диаграмму UML для разработки собственного приложения. Поэтому не стесняйтесь распространять стандарт UML 2.0 для вашего удобства. Никто не может обвинить вас в этом.
Просто используйте обычный класс в UML и назовите его HashMap
. UML является языковым агностиком и не имеет знаний о предопределенных классах Java. Или я не понял ваш вопрос?
HashMap может быть именем Java для концепции, но каждый язык программирования имеет какой-то класс Hash<>
или Map<>
, и что-то эквивалентное должно быть включено в UML, потому что многие модели включают атрибуты контейнера Hash или Map.
Некоторые инструменты поддерживают стереотип <<map>>
; если у вас есть это, я бы использовал его, если вы в основном обеспокоены визуальной интуитивностью, - но нельзя сказать, какой именно ключ подразумевается.
Графическое UML-устройство с квалифицированной ассоциацией не является интуитивным, и я подозреваю, что инструменты для преобразования в что-либо разумное в форвардном генерации кода трудно. Я хотел бы избежать этого.
Другой способ сделать это (что я обычно делаю):
Hash<Thing, String>
(будьте осторожны с порядком - сначала я использую значение, второй - ключ), создайте класс UML с именем Hash<Thing,String>
и исходящее отношение к Hash<>
, а затем сопоставьте V и K с фактическими параметрами Thing
и String
things
, тип которого - тип Hash<Thing,String>
. Например, MagicDraw поддерживает это.
Недостатком этого является то, что вы не увидите ссылку ассоциации между классом клиента и типом значения (Thing
в моем примере). Положительным моментом является то, что если вы публикуете свои модели в качестве спецификаторов программистов, это то, что мы делаем, программисты видят правильную вещь в таблицах классов, как вы можете видеть в в этом примере - translation_details attribute
.
Трудность в выполнении этой основной задачи в UML является лишь одной из многочисленных проблем с UML, и почему большинство разработчиков, с которыми я встречаюсь сегодня, не используют ее, кроме как для изображений на доске или документации.