Comments 16
А можете сами собрать в квен и дипсик. Я бы посмотрел с удовольствием. )
Вы хорошо понимаете концепт, по этому вы сможете валидировать данные, которые чаты выдают.
Сделайте на java script type module es6 html
Я бы с удовольствием, попробовал, но самому сейчас надо собрать свой проект и времени нет совсем.

Вот он сразу выдает что то. Я не могу это провалидировать.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Машина Слонимского для умножения (1844)</title>
<style>
body {
font-family: 'Courier New', monospace;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.machine {
background-color: white;
border: 2px solid #333;
border-radius: 10px;
padding: 20px;
box-shadow: 0 0 15px rgba(0,0,0,0.1);
}
.display {
font-size: 24px;
margin: 20px 0;
padding: 10px;
background-color: #eee;
border: 1px solid #ccc;
text-align: right;
min-height: 40px;
}
.controls {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
button {
padding: 15px;
font-size: 18px;
background-color: #4a4a4a;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #333;
}
.operator {
background-color: #2c3e50;
}
.equals {
background-color: #27ae60;
}
.clear {
background-color: #c0392b;
}
.history {
margin-top: 20px;
padding: 10px;
background-color: #eee;
border: 1px solid #ccc;
min-height: 100px;
}
h1 {
color: #2c3e50;
text-align: center;
}
</style>
</head>
<body>
<div class="machine">
<h1>Машина Слонимского (1844)</h1>
<div class="display" id="display">0</div>
<div class="controls">
<button class="clear" onclick="calculator.clear()">C</button>
<button onclick="calculator.inputDigit(7)">7</button>
<button onclick="calculator.inputDigit(8)">8</button>
<button onclick="calculator.inputDigit(9)">9</button>
<button class="operator" onclick="calculator.inputOperator('*')">×</button>
<button onclick="calculator.inputDigit(4)">4</button>
<button onclick="calculator.inputDigit(5)">5</button>
<button onclick="calculator.inputDigit(6)">6</button>
<button class="operator" onclick="calculator.inputOperator('-')">-</button>
<button onclick="calculator.inputDigit(1)">1</button>
<button onclick="calculator.inputDigit(2)">2</button>
<button onclick="calculator.inputDigit(3)">3</button>
<button class="operator" onclick="calculator.inputOperator('+')">+</button>
<button onclick="calculator.inputDigit(0)">0</button>
<button onclick="calculator.inputDecimal()">.</button>
<button class="equals" onclick="calculator.calculate()">=</button>
<button class="operator" onclick="calculator.inputOperator('/')">÷</button>
</div>
<div class="history" id="history"></div>
</div>
<script type="module">
class SlonimskyCalculator {
constructor() {
this.currentInput = '0';
this.previousInput = null;
this.operation = null;
this.resetInput = false;
this.history = [];
}
updateDisplay() {
const display = document.getElementById('display');
display.textContent = this.currentInput;
}
updateHistory() {
const historyElement = document.getElementById('history');
historyElement.innerHTML = this.history.map(item =>
`<div>${item}</div>`
).join('');
}
inputDigit(digit) {
if (this.resetInput) {
this.currentInput = digit.toString();
this.resetInput = false;
} else {
this.currentInput = this.currentInput === '0'
? digit.toString()
: this.currentInput + digit;
}
this.updateDisplay();
}
inputDecimal() {
if (this.resetInput) {
this.currentInput = '0.';
this.resetInput = false;
this.updateDisplay();
return;
}
if (!this.currentInput.includes('.')) {
this.currentInput += '.';
this.updateDisplay();
}
}
inputOperator(operator) {
const inputValue = parseFloat(this.currentInput);
if (this.operation && !this.resetInput) {
this.calculate();
}
this.previousInput = this.currentInput;
this.operation = operator;
this.resetInput = true;
this.history.push(`${this.previousInput} ${this.operation}`);
this.updateHistory();
}
calculate() {
if (this.operation === null || this.resetInput) return;
const prev = parseFloat(this.previousInput);
const current = parseFloat(this.currentInput);
let result;
switch (this.operation) {
case '+':
result = prev + current;
break;
case '-':
result = prev - current;
break;
case '*':
result = prev * current;
break;
case '/':
result = prev / current;
break;
default:
return;
}
// Реализация оригинального алгоритма Слонимского для умножения
if (this.operation === '*') {
result = this.slonimskyMultiply(prev, current);
}
this.currentInput = result.toString();
this.operation = null;
this.resetInput = true;
this.history.push(`${this.previousInput} ${this.operation || ''} ${current} = ${result}`);
this.history = this.history.slice(-5); // Сохраняем последние 5 операций
this.updateHistory();
this.updateDisplay();
}
// Алгоритм умножения по методу Слонимского
slonimskyMultiply(a, b) {
// Оригинальный метод использовал таблицы и последовательное сложение
// Здесь упрощенная реализация для демонстрации
let result = 0;
const isNegative = (a < 0) ^ (b < 0);
a = Math.abs(a);
b = Math.abs(b);
// Метод повторного сложения (как в оригинальной машине)
for (let i = 0; i < b; i++) {
result += a;
}
return isNegative ? -result : result;
}
clear() {
this.currentInput = '0';
this.previousInput = null;
this.operation = null;
this.updateDisplay();
}
}
// Создаем экземпляр калькулятора и делаем его глобально доступным
const calculator = new SlonimskyCalculator();
window.calculator = calculator;
calculator.updateDisplay();
</script>
</body>
</html>

Или так ещё может быть. Все зависит от степени детализации того, что требуется.
Скрытый текст
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Машина Слонимского (Демонстрация)</title>
<style>
:root {
--primary-color: #2c3e50;
--secondary-color: #3498db;
--accent-color: #e74c3c;
--success-color: #2ecc71;
--background-color: #ecf0f1;
--card-bg: #ffffff;
--border-color: #bdc3c7;
--text-color: #2c3e50;
--step-bg: #f8f9fa;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: var(--background-color);
color: var(--text-color);
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
header {
text-align: center;
margin-bottom: 30px;
padding: 20px;
background: linear-gradient(135deg, var(--primary-color), #4a6484);
color: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
h1 {
margin: 0;
font-size: 2.2em;
}
.subtitle {
font-size: 1.1em;
opacity: 0.9;
margin-top: 10px;
}
.calculator-container {
background-color: var(--card-bg);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.08);
padding: 25px;
margin-bottom: 30px;
}
.input-group {
margin-bottom: 20px;
text-align: left;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #34495e;
}
input[type="number"] {
width: 100%;
padding: 12px;
border: 1px solid var(--border-color);
border-radius: 5px;
box-sizing: border-box;
font-size: 16px;
}
button {
background-color: var(--secondary-color);
color: white;
border: none;
padding: 12px 25px;
border-radius: 6px;
cursor: pointer;
font-size: 1em;
font-weight: bold;
transition: background-color 0.3s ease;
width: 100%;
margin-top: 10px;
}
button:hover {
background-color: #2980b9;
}
button:disabled {
background-color: #bdc3c7;
cursor: not-allowed;
}
.result-section {
margin-top: 25px;
padding: 20px;
background-color: var(--step-bg);
border-radius: 8px;
border: 1px solid var(--border-color);
}
.result-title {
font-size: 1.2em;
font-weight: bold;
margin-bottom: 15px;
color: var(--primary-color);
}
.final-result {
font-size: 1.5em;
font-weight: bold;
color: var(--success-color);
text-align: center;
padding: 15px;
background-color: #e8f5e9;
border-radius: 5px;
margin-bottom: 20px;
}
.process-steps {
margin-top: 20px;
}
.step {
background-color: #fff;
border: 1px solid #eee;
border-radius: 4px;
padding: 15px;
margin-bottom: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.step-header {
font-weight: bold;
margin-bottom: 8px;
color: var(--secondary-color);
}
.explanation {
margin-top: 30px;
padding: 20px;
background-color: #fef9e7;
border-left: 5px solid #f1c40f;
border-radius: 4px;
font-size: 0.95em;
}
.explanation h3 {
margin-top: 0;
color: #f39c12;
}
.counter-display {
font-family: monospace;
background-color: #2c3e50;
color: #2ecc71;
padding: 10px;
border-radius: 4px;
text-align: center;
font-size: 1.2em;
margin: 10px 0;
min-height: 2em;
display: flex;
align-items: center;
justify-content: center;
}
.status {
padding: 8px;
border-radius: 4px;
text-align: center;
font-weight: bold;
margin-top: 10px;
}
.status-processing {
background-color: #fff3cd;
color: #856404;
}
.status-done {
background-color: #d4edda;
color: #155724;
}
.hidden {
display: none;
}
.mechanism-animation {
text-align: center;
margin: 20px 0;
min-height: 50px;
}
.gear {
display: inline-block;
font-size: 2em;
animation: rotate 2s linear infinite;
margin: 0 10px;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.carriage-move {
animation: moveCarriage 1s ease-in-out;
}
@keyframes moveCarriage {
0% { transform: translateX(0); }
50% { transform: translateX(20px); }
100% { transform: translateX(0); }
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Машина Слонимского (1844)</h1>
<p class="subtitle">Интерактивная демонстрация принципа механического умножения</p>
</header>
<main>
<section class="calculator-container">
<div class="input-group">
<label for="multiplicand">Множимое (A):</label>
<input type="number" id="multiplicand" placeholder="Введите множимое" value="123" min="0">
</div>
<div class="input-group">
<label for="multiplier">Множитель (B):</label>
<input type="number" id="multiplier" placeholder="Введите множитель" value="45" min="0">
</div>
<button id="multiply-btn">Запустить Машину Слонимского</button>
<div class="mechanism-animation hidden" id="animation-area">
<div class="gear">⚙️</div>
<div class="gear">⚙️</div>
<div class="gear">⚙️</div>
</div>
<div class="result-section">
<div class="result-title">Результат вычисления</div>
<div class="final-result" id="final-result">Результат: ?</div>
<div class="status hidden" id="status-message"></div>
<div class="process-steps">
<div class="step-header">Этапы работы машины:</div>
<div class="step">
<div class="step-header">1. Подготовка</div>
<div>Машина настраивается на множимое <strong id="prep-a">-</strong> и множитель <strong id="prep-b">-</strong>.</div>
</div>
<div class="step">
<div class="step-header">2. Позиционирование каретки</div>
<div>Каретка с цифрами множимого сдвигается в положение, соответствующее цифре множителя.</div>
</div>
<div class="step">
<div class="step-header">3. Механическое сложение</div>
<div>Происходит сложение с промежуточным результатом через вращение рукоятки.</div>
<div class="counter-display" id="accumulator">0</div>
</div>
<div class="step">
<div class="step-header">4. Сдвиг и повторение</div>
<div>Каретка сдвигается на одну позицию, и процесс повторяется для следующей цифры множителя.</div>
</div>
</div>
</div>
</section>
<section class="explanation">
<h3>Как работала Машина Слонимского</h3>
<p><strong>Принцип действия:</strong></p>
<ol>
<li><strong>Настройка:</strong> Множимое (например, 123) устанавливалось на каретке с помощью циферблатов или штырей.</li>
<li><strong>Циклическое сложение:</strong> Для каждой цифры множителя (например, 4 и 5 в числе 45):
<ul>
<li>Каретка сдвигалась влево на соответствующее количество разрядов (единицы, десятки и т.д.).</li>
<li>Рукоятка поворачивалась столько раз, какова цифра множителя (4 раза для цифры 4, 5 раз для цифры 5).</li>
<li>При каждом повороте множимое прибавлялось к накапливаемому результату через систему зубчатых колес.</li>
</ul>
</li>
<li><strong>Результат:</strong> После обработки всех цифр множителя на счетных колесах отображался окончательный результат.</li>
</ol>
<p><strong>Пример вычисления 123 × 45:</strong></p>
<ul>
<li>123 × 5 = 615 (сдвиг 0 разрядов)</li>
<li>123 × 4 = 492 (сдвиг 1 разряд влево → 4920)</li>
<li>615 + 4920 = 5535</li>
</ul>
</section>
</main>
</div>
<script type="module">
// --- Модуль "Машина Слонимского" ---
/**
* @module SlonimskyMachine
* @description Модуль, имитирующий работу оригинальной Машины Слонимского.
*/
/**
* @function multiplySlonimskyCore
* @description Имитирует механическое умножение на Машине Слонимского.
* Реализует циклы сложения и сдвиги каретки.
* @param {number} multiplicand - Множимое (A)
* @param {number} multiplier - Множитель (B)
* @param {Function} onStep - Callback для обновления UI на каждом шаге
* @returns {Promise<number>} Произведение A и B
*/
async function multiplySlonimskyCore(multiplicand, multiplier, onStep) {
// Начальное состояние "счетного механизма" (аккумулятора)
let accumulator = 0;
const multiplicandStr = String(multiplicand);
const multiplierStr = String(multiplier);
onStep('start', { multiplicand, multiplier });
// Проходим по цифрам множителя справа налево (от младших разрядов)
for (let i = multiplierStr.length - 1; i >= 0; i--) {
const digit = parseInt(multiplierStr[i], 10);
const placeValue = Math.pow(10, multiplierStr.length - 1 - i); // 1, 10, 100...
onStep('digit_start', { digit, placeValue, step: multiplierStr.length - i });
// Для каждой цифры множителя выполняем сложение столько раз, какова её величина
// Это имитирует поворот рукоятки
for (let turn = 1; turn <= digit; turn++) {
// Вычисляем промежуточное слагаемое (множимое * цифру * разряд)
const addend = multiplicand * digit * (placeValue / Math.pow(10, multiplierStr.length - 1 - i));
// Имитация механического сложения
accumulator += multiplicand * placeValue;
onStep('turn', {
turn,
digit,
placeValue,
addend: multiplicand * placeValue,
accumulator
});
// Небольшая задержка для демонстрации
await new Promise(resolve => setTimeout(resolve, 300));
}
onStep('digit_end', { digit, placeValue });
}
onStep('done', { result: accumulator });
return accumulator;
}
// --- Логика пользовательского интерфейса ---
document.addEventListener('DOMContentLoaded', () => {
const multiplicandInput = document.getElementById('multiplicand');
const multiplierInput = document.getElementById('multiplier');
const multiplyButton = document.getElementById('multiply-btn');
const finalResultDiv = document.getElementById('final-result');
const accumulatorDisplay = document.getElementById('accumulator');
const statusMessage = document.getElementById('status-message');
const animationArea = document.getElementById('animation-area');
const prepADisplay = document.getElementById('prep-a');
const prepBDisplay = document.getElementById('prep-b');
// Функция для обновления UI в процессе вычисления
function updateUI(event, data) {
switch(event) {
case 'start':
prepADisplay.textContent = data.multiplicand;
prepBDisplay.textContent = data.multiplier;
statusMessage.textContent = `Подготовка: множимое=${data.multiplicand}, множитель=${data.multiplier}`;
statusMessage.className = 'status status-processing';
statusMessage.classList.remove('hidden');
animationArea.classList.remove('hidden');
finalResultDiv.textContent = 'Результат: вычисляется...';
break;
case 'digit_start':
statusMessage.textContent = `Обработка цифры ${data.digit} (разряд ${data.placeValue})...`;
accumulatorDisplay.parentElement.classList.add('carriage-move');
setTimeout(() => {
accumulatorDisplay.parentElement.classList.remove('carriage-move');
}, 1000);
break;
case 'turn':
accumulatorDisplay.textContent = data.accumulator;
statusMessage.textContent = `Поворот ${data.turn}/${data.digit} для цифры ${data.digit}. Добавлено: ${data.addend}`;
break;
case 'digit_end':
statusMessage.textContent = `Цифра ${data.digit} обработана.`;
break;
case 'done':
finalResultDiv.textContent = `Результат: ${data.result}`;
statusMessage.textContent = 'Вычисление завершено!';
statusMessage.className = 'status status-done';
animationArea.classList.add('hidden');
break;
}
}
// Обработчик нажатия кнопки
multiplyButton.addEventListener('click', async () => {
const multiplicand = parseInt(multiplicandInput.value, 10);
const multiplier = parseInt(multiplierInput.value, 10);
// Валидация ввода
if (isNaN(multiplicand) || isNaN(multiplier) || multiplicand < 0 || multiplier < 0) {
finalResultDiv.textContent = 'Ошибка: Введите неотрицательные целые числа.';
finalResultDiv.style.color = '#e74c3c';
return;
}
multiplyButton.disabled = true;
finalResultDiv.style.color = '#2c3e50';
try {
// Запуск "машины"
const product = await multiplySlonimskyCore(multiplicand, multiplier, updateUI);
console.log(`[Слонимский] Результат: ${multiplicand} × ${multiplier} = ${product}`);
} catch (error) {
console.error("[Ошибка] Не удалось выполнить умножение:", error);
finalResultDiv.textContent = `Ошибка вычисления: ${error.message}`;
finalResultDiv.style.color = '#e74c3c';
statusMessage.textContent = `Ошибка: ${error.message}`;
statusMessage.className = 'status status-error';
statusMessage.classList.remove('hidden');
} finally {
multiplyButton.disabled = false;
}
});
});
</script>
</body>
</html>

Скрытый текст
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Машина Слонимского для умножения (1844) - Точная реплика</title>
<style>
body {
font-family: 'Times New Roman', serif;
background-color: #f0e6d2;
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.machine-container {
background-color: #8B4513;
border: 15px solid #5D4037;
border-radius: 20px;
padding: 30px;
box-shadow: 0 0 30px rgba(0,0,0,0.5);
width: 800px;
position: relative;
}
.machine-title {
text-align: center;
color: #FFD700;
font-size: 24px;
margin-bottom: 20px;
text-shadow: 2px 2px 4px #000;
}
.machine-body {
background-color: #A67C52;
border: 10px solid #5D4037;
border-radius: 10px;
padding: 20px;
}
.display-panel {
background-color: #D2B48C;
border: 5px solid #5D4037;
padding: 15px;
margin-bottom: 20px;
text-align: right;
font-size: 28px;
height: 50px;
overflow: hidden;
position: relative;
}
.display-number {
position: absolute;
right: 15px;
font-family: 'Courier New', monospace;
}
.levers-container {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.digit-levers {
display: flex;
gap: 15px;
}
.lever {
width: 30px;
height: 100px;
background: linear-gradient(to right, #C0C0C0, #E0E0E0, #C0C0C0);
border: 3px solid #333;
border-radius: 5px;
cursor: pointer;
position: relative;
transition: transform 0.3s;
transform-origin: bottom center;
}
.lever:hover {
background: linear-gradient(to right, #A0A0A0, #C0C0C0, #A0A0A0);
}
.lever:active {
transform: rotate(-15deg);
}
.lever-label {
position: absolute;
bottom: -25px;
left: 0;
right: 0;
text-align: center;
font-weight: bold;
color: #000;
}
.operation-levers {
display: flex;
flex-direction: column;
gap: 10px;
}
.operation-lever {
width: 80px;
height: 40px;
background: linear-gradient(to bottom, #C0C0C0, #E0E0E0, #C0C0C0);
border: 3px solid #333;
border-radius: 5px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
}
.operation-lever:hover {
background: linear-gradient(to bottom, #A0A0A0, #C0C0C0, #A0A0A0);
}
.operation-lever:active {
transform: translateY(3px);
}
.result-lever {
width: 120px;
height: 50px;
background: linear-gradient(to right, #FF8C00, #FFA500, #FF8C00);
border: 3px solid #8B0000;
border-radius: 5px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
margin: 0 auto;
}
.result-lever:hover {
background: linear-gradient(to right, #E07C00, #FF9500, #E07C00);
}
.result-lever:active {
transform: translateY(5px);
}
.history-panel {
background-color: #D2B48C;
border: 5px solid #5D4037;
padding: 10px;
margin-top: 20px;
height: 100px;
overflow-y: auto;
font-family: 'Courier New', monospace;
}
.history-entry {
margin-bottom: 5px;
border-bottom: 1px dashed #8B4513;
padding-bottom: 3px;
}
.machine-footer {
text-align: center;
color: #FFD700;
margin-top: 15px;
font-style: italic;
}
</style>
</head>
<body>
<div class="machine-container">
<div class="machine-title">АРИФМОМЕТРЪ СЛОНИМСКАГО (1844)</div>
<div class="machine-body">
<div class="display-panel">
<div class="display-number" id="display">0</div>
</div>
<div class="levers-container">
<div class="digit-levers">
<div class="lever" onclick="moveLever(7)" data-digit="7">
<div class="lever-label">7</div>
</div>
<div class="lever" onclick="moveLever(8)" data-digit="8">
<div class="lever-label">8</div>
</div>
<div class="lever" onclick="moveLever(9)" data-digit="9">
<div class="lever-label">9</div>
</div>
<div class="lever" onclick="moveLever(4)" data-digit="4">
<div class="lever-label">4</div>
</div>
<div class="lever" onclick="moveLever(5)" data-digit="5">
<div class="lever-label">5</div>
</div>
<div class="lever" onclick="moveLever(6)" data-digit="6">
<div class="lever-label">6</div>
</div>
<div class="lever" onclick="moveLever(1)" data-digit="1">
<div class="lever-label">1</div>
</div>
<div class="lever" onclick="moveLever(2)" data-digit="2">
<div class="lever-label">2</div>
</div>
<div class="lever" onclick="moveLever(3)" data-digit="3">
<div class="lever-label">3</div>
</div>
<div class="lever" onclick="moveLever(0)" data-digit="0">
<div class="lever-label">0</div>
</div>
</div>
<div class="operation-levers">
<div class="operation-lever" onclick="setOperation('+')">Сложение</div>
<div class="operation-lever" onclick="setOperation('-')">Вычитание</div>
<div class="operation-lever" onclick="setOperation('*')">Умножение</div>
<div class="operation-lever" onclick="setOperation('/')">Деление</div>
<div class="operation-lever" onclick="clearMachine()">Сброс</div>
</div>
</div>
<div class="result-lever" onclick="calculate()">Получить результат</div>
<div class="history-panel" id="history"></div>
</div>
<div class="machine-footer">Изобретено Х.З. Слонимским в 1844 году</div>
</div>
<script>
// Состояние машины
const machineState = {
currentValue: 0,
storedValue: null,
operation: null,
isNewNumber: true,
history: []
};
// Элементы интерфейса
const display = document.getElementById('display');
const historyElement = document.getElementById('history');
// Анимация рычагов
function animateLever(leverElement) {
leverElement.style.transform = 'rotate(-15deg)';
setTimeout(() => {
leverElement.style.transform = 'rotate(0)';
}, 300);
}
// Обработка движения рычага
function moveLever(digit) {
const lever = document.querySelector(`.lever[data-digit="${digit}"]`);
animateLever(lever);
if (machineState.isNewNumber) {
machineState.currentValue = digit;
machineState.isNewNumber = false;
} else {
machineState.currentValue = machineState.currentValue * 10 + digit;
}
updateDisplay();
}
// Установка операции
function setOperation(op) {
if (machineState.operation && !machineState.isNewNumber) {
calculate();
}
machineState.storedValue = machineState.currentValue;
machineState.operation = op;
machineState.isNewNumber = true;
addHistory(`${machineState.storedValue} ${op}`);
}
// Вычисление результата
function calculate() {
if (!machineState.operation || machineState.isNewNumber) return;
let result;
const a = machineState.storedValue;
const b = machineState.currentValue;
switch (machineState.operation) {
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
// Оригинальный метод умножения Слонимского
result = slonimskyMultiplication(a, b);
break;
case '/':
result = a / b;
break;
default:
return;
}
machineState.currentValue = result;
machineState.operation = null;
machineState.isNewNumber = true;
addHistory(`= ${result}`);
updateDisplay();
// Анимация рычага результата
const resultLever = document.querySelector('.result-lever');
resultLever.style.transform = 'translateY(5px)';
setTimeout(() => {
resultLever.style.transform = 'translateY(0)';
}, 200);
}
// Оригинальный алгоритм умножения Слонимского
function slonimskyMultiplication(a, b) {
// В оригинале использовались специальные таблицы умножения
// и механическое сложение частичных произведений
// Для простоты реализуем через последовательное сложение
// как это делала механическая версия
let result = 0;
const isNegative = (a < 0) ^ (b < 0);
a = Math.abs(a);
b = Math.abs(b);
for (let i = 0; i < b; i++) {
result += a;
}
return isNegative ? -result : result;
}
// Сброс машины
function clearMachine() {
machineState.currentValue = 0;
machineState.storedValue = null;
machineState.operation = null;
machineState.isNewNumber = true;
updateDisplay();
addHistory("--- Машина сброшена ---");
}
// Обновление дисплея
function updateDisplay() {
display.textContent = machineState.currentValue;
}
// Добавление записи в историю
function addHistory(entry) {
machineState.history.push(entry);
if (machineState.history.length > 5) {
machineState.history.shift();
}
historyElement.innerHTML = machineState.history
.map(item => `<div class="history-entry">${item}</div>`)
.join('');
historyElement.scrollTop = historyElement.scrollHeight;
}
// Инициализация
updateDisplay();
addHistory("Машина готова к работе");
</script>
</body>
</html>
Простите, но это всё-таки не арифмометр, а механизированная таблица.
Да, конечно. То так разместить более 3000 цифр и букв, что практически автоматически получаются 8 произведенией, как это сделал Слонимский, -- надо суметь! Я знаю, что один человек (не в России) сделал реконструкцию машины. С механизмами смещения цилиндров и др. Но без верхней панели с окошками. Красиво!
Спасибо за все. Буду разбираться.
Общая схема модели здесь:
https://drive.google.com/file/d/1DMrecUT3wB2a4rxLL3n-MkrNYh2CElFS/view?usp=sharing
Элементы модели
· Двумерный массив win окон ввода, 11 строк, 8 столбцов
· Двумерный массив dig цифр, 56 строк, 40 столбцов
· Двумерный массив point указателей, 14 строк, 40 столбцов; элементы 2-символьные
· Одномерный массив row1 ряда 1, 40 элементов; элементы 2-символьные
· Массив горизонтальных ScrollBox 8 элементов:
- ScrollBox 0: min = 0, max = 3
- ScrollBox 7: min = 0, max = 9
- остальные, min = 0, max = 39
· Массив вертикальных ScrollBox 7 элементов, min = 1, max = 7
Значения в массивах dig цифр, point указателей, row1 ряда 1 известны (заполню я)
Начальная ситуация
Значения в массиве окон;
- первые 56 строк – 0
- последняя строка – a0, a1, a2, a3, a4, a5, a6, a7, a8, a9
- остальные 14 строк – a7
Связи элементов
Значения во всех окнах берутся из трех массивов (dig цифр, point указателей, row1 ряда 1), и зависят от положения всех ScrollBox:
· при перемещении горизонтальных ScrollBox 1, 2, …, 6 меняются значения в соответствующем столбце массива окон по общему правилу
· при перемещении горизонтального ScrollBox 0 меняются значения в первом столбце массива окон по отдельному правилу
· при перемещении горизонтального ScrollBox 7 меняются значения в последнем столбце массива окон по отдельному правилу
· при перемещении всех вертикальных ScrollBox меняются значения в соответствующем столбце массива окон по общему правилу
ScrollBox 6 – в столбце 6 окон
ScrollBox 5 – в столбце 5
ScrollBox 4 – в столбце 4
ScrollBox 3 – в столбце 3
ScrollBox 2 – в столбце 2
ScrollBox 1 – в столбце 1
ScrollBox 0 – в столбце 0
Ну вам достаточно более ли менее адекватную модель за основу взять. И попросить написать нужные методы и сделать нужный набор параметров для управления.
Например реальный интерфейс наверное будет быстрее руками нарисовать, но под него все параметры расчитать можно.
html удобно что вы в браузере можете сразу все посмотреть и по расчитывать.
Спасибо. Возникли 2 принципиальных вопроса.
Можно ли вместо нескольких текстовых полей (для вывода цифр) использовать массив полей?
Возможно ли использование элемента "полоса прокрутки" не для скроллинга страниц, а для выбора (изменения) значений из некоторого диапазона (как, например, в регуляторах уровня громкости)?/
Как я писал, интерфейс модели машины - 88 текстовых полей и элементы для изменения/задания значений в них (лучше полосы прокрутки, хуже - кнопки > <).
Процедура обработки события этих элементов будет менять содержимой текстовых окон.
И это - вся модель (кроме истории и хэлпа).
Статья слишком неполная. Она не содержит никакой информации по машине, которые не были бы по другим ссылкам.
По факту - засоряет выдачу гугла.
Моя задача была - найти Вас или такого, как Вы.
А всё новое я написал на сайте Стефана Вайса (самый крупный специалист по ручным и механическим вычислительным устройствам, он результаты оценил и опубликовал) и напишу на сайте Виртуального компьютерного музея (где уже есть ряд моих публикаций)
Машина Слонимского для умножения (1844 г.): новые результаты и веб-модель