27. 좌표·각도 양자화(quantization) 직렬화의 경계 처리 결함 (C#)
난이도 하 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// ─────────────────────────────────────────────────────────────
// 시나리오: 대역폭 절약을 위해 이동 패킷의 위치(x,y,z)와 바라보는 각도를
// float 그대로 보내지 않고 16비트 정수로 양자화(quantize)해 전송한다.
// 수신 측은 역양자화(dequantize)해 월드 좌표/각도로 복원한다.
// 월드는 [0, WorldSize] 정육면체이고, 각도는 라디안이다.
//
// 클라가 보내는 좌표는 넉백/추락/스킬 이동/부동소수 오차 등으로
// 가끔 월드 경계를 살짝 벗어나거나 음수가 될 수 있고, 각도는 누적 회전으로
// 2π를 넘거나 음수가 될 수 있다(정규화 전 값).
//
// 요구사항:
// - 양자화→역양자화 왕복 후 좌표/각도가 "원래 값에 가깝게" 복원되어야 하고,
// 특히 범위를 벗어난 입력이 들어와도 엉뚱한 위치로 튀면 안 된다.
//
// 과제: (A)(B) 지점을 검토하라. 경계를 벗어난 입력(예: x = -0.5, x = WorldSize+3,
// angle = -0.1, angle = 7.0)이 들어올 때 복원 결과가 어떻게 되는지
// 구체적으로 설명하고, 수정안을 제시하라.
// ─────────────────────────────────────────────────────────────
using System;
namespace Net
{
public struct QuantPos { public ushort X, Y, Z; }
public static class Quantizer
{
public const float WorldSize = 4096.0f;
private const float TwoPi = (float)(2 * Math.PI);
public static QuantPos QuantizePos(float x, float y, float z)
{
QuantPos q;
// (A)
q.X = (ushort)(x / WorldSize * 65535.0f);
q.Y = (ushort)(y / WorldSize * 65535.0f);
q.Z = (ushort)(z / WorldSize * 65535.0f);
return q;
}
public static (float x, float y, float z) DequantizePos(QuantPos q)
{
return (q.X / 65535.0f * WorldSize,
q.Y / 65535.0f * WorldSize,
q.Z / 65535.0f * WorldSize);
}
public static ushort QuantizeAngle(float radians)
{
// (B)
return (ushort)(radians / TwoPi * 65535.0f);
}
public static float DequantizeAngle(ushort q) => q / 65535.0f * TwoPi;
}
} 결함 코드 · C++
// ─────────────────────────────────────────────────────────────
// 시나리오: 대역폭 절약을 위해 이동 패킷의 위치(x,y,z)와 각도를 float 그대로
// 보내지 않고 16비트 정수로 양자화(quantize)해 전송한다. 수신 측은
// 역양자화(dequantize)해 복원한다. 월드는 [0, kWorldSize] 정육면체,
// 각도는 라디안이다.
//
// 클라가 보내는 좌표는 넉백/추락/스킬 이동/부동소수 오차로 가끔 월드 경계를
// 살짝 벗어나거나 음수가 될 수 있고, 각도는 누적 회전으로 2π를 넘거나
// 음수가 될 수 있다(정규화 전 값).
//
// 요구사항:
// - 왕복(quantize→dequantize) 후 값이 원래에 가깝게 복원되어야 하고,
// 범위를 벗어난 입력이 들어와도 엉뚱한 위치로 튀면 안 된다.
//
// 과제: (A)(B) 지점을 검토하라. 경계 밖 입력(x=-0.5, x=kWorldSize+3,
// angle=-0.1, angle=7.0)이 들어올 때 복원 결과가 어떻게 되는지 설명하고
// 수정안을 제시하라.
// ─────────────────────────────────────────────────────────────
#include <cstdint>
namespace net {
constexpr float kWorldSize = 4096.0f;
constexpr float kTwoPi = 6.2831853071795864769f;
struct QuantPos { uint16_t x, y, z; };
inline QuantPos quantizePos(float x, float y, float z) {
QuantPos q;
// (A)
q.x = static_cast<uint16_t>(x / kWorldSize * 65535.0f);
q.y = static_cast<uint16_t>(y / kWorldSize * 65535.0f);
q.z = static_cast<uint16_t>(z / kWorldSize * 65535.0f);
return q;
}
inline void dequantizePos(const QuantPos& q, float& x, float& y, float& z) {
x = q.x / 65535.0f * kWorldSize;
y = q.y / 65535.0f * kWorldSize;
z = q.z / 65535.0f * kWorldSize;
}
inline uint16_t quantizeAngle(float radians) {
// (B)
return static_cast<uint16_t>(radians / kTwoPi * 65535.0f);
}
inline float dequantizeAngle(uint16_t q) {
return q / 65535.0f * kTwoPi;
}
} // namespace net 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.